r error 4 (Error in eval(ele) : objeto ‘opts_knit’ no encontrado
)
Introducción
El método de series temporales jerárquicas es una técnica avanzada
utilizada para modelar y predecir datos temporales que exhiben una
estructura jerárquica natural. Su aplicación eficaz puede mejorar
significativamente la precisión de los pronósticos y facilitar la toma
de decisiones estratégicas en diversas áreas de aplicación, es
especialmente útil en situaciones donde los datos se pueden descomponer
en múltiples niveles de agregación, como por ejemplo, desplazamientos
internos, regiones y país.
Componentes Principales
Descomposición Jerárquica: Divide los datos en
múltiples series temporales interrelacionadas que se organizan en una
estructura de árbol jerárquico. Por ejemplo, los desplazamientos
internos pueden descomponerse en desplazamientos internos por región, y
a su vez, los desplazamientos internos por región se descomponen por
estados.
Modelado Independiente y Consistente: Cada serie
temporal dentro de la jerarquía se modela de forma independiente
utilizando métodos de series temporales tradicionales como ARIMA o
métodos más avanzados como modelos de espacio de estado.
Consistencia Agregada: Los pronósticos de las
series temporales individuales se agregan de manera coherente para
generar pronósticos precisos y consistentes en todos los niveles de la
jerarquía.
Consideraciones Prácticas
- Software Especializado: Utilización de herramientas
como
R (con paquetes como hts) o
Python para implementar y automatizar el método.
- Validación y Ajuste: Validar los modelos en
múltiples niveles de la jerarquía y ajustar según sea necesario para
mejorar la precisión.
Encuesta Nacional de Ocupación y Empleo (ENOE)
La Encuesta Nacional de Ocupación y Empleo (ENOE),
realizada por el Instituto Nacional de Estadística y Geografía
(INEGI), es una herramienta esencial para medir la dinámica
del mercado laboral en México. Proporciona datos detallados sobre la
ocupación, el empleo, el desempleo y otras características relevantes de
la población económicamente activa.
Objetivos Principales
Medición de la Población Económicamente Activa
(PEA): Identificar la proporción de la población que participa
en el mercado laboral, incluyendo tanto a las personas ocupadas como a
las desocupadas.
Análisis del Empleo: Proporcionar información
sobre las características del empleo, incluyendo la naturaleza del
trabajo, las condiciones laborales, los sectores económicos y las tasas
de empleo formal e informal.
Evaluación del Desempleo: Estimar la tasa de
desempleo y analizar las características de la población desocupada,
incluyendo la duración del desempleo y los esfuerzos de búsqueda de
empleo.
Información Socioeconómica: Recopilar datos
sobre la educación, los ingresos y otras variables socioeconómicas que
afectan y son afectadas por el empleo y el desempleo.
Componentes Principales
- Encuestas Trimestrales: La ENOE se realiza de
manera continua, con resultados publicados trimestralmente, lo que
permite un seguimiento cercano de las tendencias laborales.
- Cobertura Nacional: La encuesta abarca todas las
entidades federativas de México, ofreciendo una visión comprensiva y
detallada del mercado laboral a nivel nacional y regional.
- Amplitud de Temas: Incluye información sobre empleo
formal e informal, subempleo, ocupaciones, ingresos, condiciones de
trabajo y más.
Aplicaciones
Políticas Públicas: Los datos de la ENOE son cruciales
para la formulación y evaluación de políticas laborales, educativas y
económicas.
Investigación Académica: Proporciona una base de datos
rica para estudios sobre el mercado laboral, la economía del trabajo y
la sociología del empleo.
Análisis Sectorial: Ayuda a identificar tendencias y
desafíos específicos en distintos sectores económicos, informando
decisiones empresariales y gubernamentales.
Consideraciones Prácticas
- Acceso a Datos: Los datos de la ENOE están
disponibles públicamente a través del INEGI, facilitando su uso para
análisis y estudios detallados.
- Metodología Rigurosa: La encuesta sigue estándares
metodológicos estrictos, asegurando la calidad y confiabilidad de los
datos.
- Actualización Continua: La ENOE se actualiza
continuamente, permitiendo un monitoreo preciso de las dinámicas
laborales a lo largo del tiempo.
Diseño conceptual
La población objetivo de la encuesta está conformada por todos los
que residen habitualmente las viviendas seleccionadas. Los instrumentos
de captación más importantes son el
Cuestionario Sociodemográfico (CS) y el
Cuestionario de Ocupación y Empleo (COE). La información
referente a los hogares y a las características sociodemográficas de los
residentes de la vivienda se registra en el CS, mientras
que el COE contiene variables que identifican en primer
lugar la condición de actividad y en segundo término preguntas
específicas para cada uno de los universos. Es necesario mencionar que
el COE se levanta a la población de 12 años en adelante,
sin embargo, por cuestiones metodológicas del marco de la OCDE se
pública para la población de 15 años en adelante.
Diseño temporal
La ENOE es una encuesta panel de rotatorio, es decir,
tiene una muestra de viviendas dividida en 5 paneles de rotación. De los
cuales, rota uno cada trimestre; conservando de esta manera, el 80 por
ciento de la muestra entre dos trimestres consecutivos. Lo que permite
llevar a cabo dos importantes actividades: sustituir el marco muestral y
cambiar esquema de muestreo.
Por otra parte, toda la cantidad de información recabada de la misma
unidad de muestreo en dos o más periodos consecutivos permitirá
teóricamente incrementar la precisión de las estimaciones,
principalmente del cambio en ellas. Cochran (1977) coincide con esto y
además establece que, en la obtención de las estimaciones actuales, se
gana la misma precisión si se conserva la muestra inicial o se cambia en
cada ocasión.
Condición de Residencia
Un aspecto relevante por considerar fue identificar la condición de
residencia, a quienes de los residentes continuaban viviendo en el hogar
o en otros términos a quienes no han estado en un proceso de transición
de residencia, así como los ausentes definitivos y a los nuevos
residentes. Al respecto, cabe acotar, que el diseño conceptual del
Cuestionario Sociodemográfico identifica a quienes ya no se encuentran
por haber partido a otro lugar por diversas causas entre éstas por
mortalidad (Ausentes Definitivos) y distingue quienes son
nuevos en lo del mismo hogar por haber arribado de algún lugar otro
lugar por diversas causas entre ellas el nacimiento
(Nuevo Residentes).
Motivo de la migración
Los datos son recopilados de la ENOE, siendo, la fuente
principal de información sobre el mercado laboral mexicano al ofrecer
datos de manera trimestral de la fuerza de trabajo, ocupación, la
informalidad laboral, la subocupación y desocupación.
La ENOE inicia su levantamiento en 2005 y se repite en intervalos
regulares de tiempo, captando la información a nivel nacional. Este tipo
de encuesta permite captar y conocer de mejor manera las características
socioeconómicas de la población mexicana de 15 años y más.
El objetivo del trabajo es implementar y comparar las diferentes
series de tiempo de manera jerárquica y permitir el desglose de las
causas de migración.
Indicadores
Tomando las preguntas del cuestionario de las cuales son más de
trescientas bases de datos con 150 mil casos a nivel
nacional en los diferentes periodos de tiempo.
Las coberturas geográficas o dominios de estudio para las cuales se
generan estimaciones son:
Ciudad Autorepresentada
Entidad Federativa
Nacional
Se toma como referencia la pregunta cs_ad_mot
Motivo de la migración , en la cual se desglosa en las
siguientes categorías.
- Trabajo
- Estudio
- Se casó o unió
- Se separó o divorció
- Problemas de salud
- Reunirse con la familia
- Inseguridad pública
- Falleció
- Otro Motivo
- No sabe
De las cuales solo se toman 5 casos para el propósito del presente
trabajo.
Base de datos
Se cargan las bases de datos que contienen los cinco principales
motivos de la migración, tomando como referencia los datos del 2005 al
2019.
(detectDates = TRUE); las fechas se detectan y se
convierten automáticamente en objetos de fecha en R.
T.Trabajo <- read.xlsx(paste0(here::here(), "/Base de datos/Resultados ENOE.xlsx"),
sheet = "Trabajo",
colNames = TRUE, detectDates = TRUE)
T.Estudio <- read.xlsx(paste0(here::here(), "/Base de datos/Resultados ENOE.xlsx"),
sheet = "Estudio",
colNames = TRUE,
detectDates = TRUE)
T.Union <- read.xlsx(paste0(here::here(), "/Base de datos/Resultados ENOE.xlsx"),
sheet = "Union",
colNames = TRUE,
detectDates = TRUE)
T.Divorcio <- read.xlsx(paste0(here::here(), "/Base de datos/Resultados ENOE.xlsx"),
sheet = "Divorcio",
colNames = TRUE,
detectDates = TRUE)
T.Familia <- read.xlsx(paste0(here::here(), "/Base de datos/Resultados ENOE.xlsx"),
sheet = "Reunirse con un familiar",
colNames = TRUE,
detectDates = TRUE)
Se divide entre la población, debido a que si toman los absolutos de
las personas que cambiaron de residencia por alguno de los diferentes
motivos de ausencia. Estos tienden a ser mayores en algunas ciudades,
debido se tiene mayor densidad de población. Permitiendo así la
comparabilidad entre ciudades por una razón de cada 1000 personas.
Se define la función llamada divide_columns que toma dos
data.frames (df1 y df2). La función:
- Extrae todas las columnas de df1 y df2 desde la segunda columna en
adelante.
- Usa la función
map2_dfc del paquete purrr
para dividir cada par de columnas correspondientes de df1 y df2,
multiplicando el resultado por 1000.
- Se reconstruye el data.frame resultante combinando la primera
columna de df1 con las columnas resultantes de la división.
#Población Total
T.Poblacion <- read.xlsx(paste0(here::here(), "/Base de datos/Resultados ENOE.xlsx"),
sheet = "Población",
colNames = TRUE,
detectDates = TRUE)
# Vector de tiempo
Periodo <- T.Poblacion$Periodo #Se guarda el vector tiempo
#Creamos una función personalizada para dividir los elementos desde la segunda columna en adelante
divide_columns <- function(df1, df2) {
df1_cols <- df1[, 2:ncol(df1)]
df2_cols <- df2[, 2:ncol(df2)]
# Aplicamos la división usando map2
result_cols <- map2_dfc(df1_cols, df2_cols, ~ .x / .y * 1000)
# Reconstruimos el data.frame con la primera columna de df1 y las columnas resultantes
result <- bind_cols(df1[, 1, drop = FALSE], result_cols)
result
}
tablas <- ls(pattern = "T.")
for(i in 1:6){
assign(paste0(tablas[i]), divide_columns(get(paste0(tablas[i])), T.Poblacion))
}
# Todo en un data.frame
mydata <- do.call(cbind.data.frame, list(T.Trabajo,
T.Estudio %>% select(-c("Periodo")) ,
T.Union %>% select(-c("Periodo")) ,
T.Divorcio %>% select(-c("Periodo")) ,
T.Familia %>% select(-c("Periodo"))))
Tasas de migración por algún motivo de ausencia
| Periodo |
Centro_ACA_Trabajo |
Centro_CUER_Trabajo |
Centro_MEX_Trabajo |
Centro_PACH_Trabajo |
Centro_PUE_Trabajo |
| 2005-01-01 |
8076 |
4255 |
67493 |
2228 |
6201 |
| 2005-04-01 |
7798 |
4651 |
76577 |
2584 |
8752 |
| 2005-07-01 |
4224 |
3123 |
43216 |
1135 |
4350 |
| 2005-10-01 |
2057 |
2360 |
23673 |
1013 |
5130 |
| 2006-01-01 |
4624 |
3006 |
22306 |
1066 |
4730 |
| 2006-04-01 |
2624 |
2530 |
36413 |
1073 |
2832 |
A continuación se estructura la jerarquía de los niveles de acuerdo
al tipo de desagregación geográfica, en la cual se agrupan las 32
ciudades autorepresentadas en regiones.
- Se consideraron 5 regiones del país para que los cálculos no fueran
tan extensos a la hora de interpretarlos.
Estructura general de las regiones
| Región |
Clave |
Ciudad |
| Centro |
11 |
Acapulco |
| Centro |
24 |
Cuernavaca |
| Centro |
01 |
México |
| Centro |
32 |
Pachuca |
| Centro |
04 |
Puebla |
| Centro |
14 |
Toluca |
| Centro |
29 |
Tlaxcala |
| Noreste |
21 |
Durango |
| Noreste |
03 |
Monterrey |
| Noreste |
06 |
San Luis Potosí |
| Noreste |
15 |
Saltillo |
| Noreste |
09 |
Tampico |
| Noroeste |
08 |
Chihuahua |
| Noroeste |
19 |
Culiacán |
| Noroeste |
20 |
Hermosillo |
| Noroeste |
30 |
La Paz |
| Noroeste |
18 |
Tijuana |
| Occidente |
12 |
Aguascalientes |
| Occidente |
27 |
Colima |
| Occidente |
02 |
Guadalajara |
| Occidente |
05 |
León |
| Occidente |
13 |
Morelia |
| Occidente |
28 |
Querétaro |
| Occidente |
22 |
Tepic |
| Occidente |
26 |
Zacatecas |
| Sureste |
31 |
Cancún |
| Sureste |
23 |
Campeche |
| Sureste |
07 |
Mérida |
| Sureste |
25 |
Oaxaca |
| Sureste |
17 |
Tuxtla Guutiérrez |
| Sureste |
10 |
Veracruz |
| Sureste |
16 |
Villahermosa |
Estructura jerárquica
Cada uno de estos grupos se desglosan en categorías que están
anidadas dentro de las categorías de grupos más grandes como 32 ciudades
autorepresentadas y 5 regiones, por lo que se hace una recolección de
160 series de tiempo que siguen una estructura de agregación
jerárquica.
Esquema Jerárquico
El número de series en el nivel inferior es de 160 series, por lo que
las observaciones en el nivel último sumaran a las observaciones del
nivel anterior y así sucesivamente.
Los 5 motivos de la ausencia se transforman en series de tiempo, para
analizarlos cada uno posteriormente. Los datos se convierten en objetos
de series temporales (ts) utilizando la función
ts. Cada serie temporal se define con:
start = 2005: El primer año de la serie temporal es
2005.
end = 2019: El último año de la serie temporal es
2019.
frequency = 4: La frecuencia de la serie temporal es
trimestral (4 trimestres por año).
ts.Trabajo <- ts(T.Trabajo %>% select(., c(2:length(.))), start = 2005, end = 2019, frequency = 4)
ts.Estudio <- ts(T.Estudio %>% select(., c(2:length(.))), start = 2005, end = 2019, frequency = 4)
ts.Union <- ts(T.Union %>% select(., c(2:length(.))), start = 2005, end = 2019, frequency = 4)
ts.Divorcio <- ts(T.Divorcio %>% select(., c(2:length(.))), start = 2005, end = 2019, frequency = 4)
ts.Familia <- ts(T.Familia %>% select(., c(2:length(.))), start = 2005, end = 2019, frequency = 4)
Motivo de la ausencia: Trabajo
Se analiza cómo caso particular el motivo de la ausencia por
trabajo, para empezar familiarizarse con la jerarquización del
modelo y posteriormente agregar de manera general los demás motivos
expuestos al inicio.
Utilizando la función dygraph permite observar de manera
iterativa multiples series de tiempo.
dyRangeSelector(): Agrega un selector de rango (un
control deslizante) que permite al usuario seleccionar un rango de
fechas para visualizar en el gráfico.
dyLegend(width = 650): Añade una leyenda al gráfico y
establece su ancho a 650 píxeles.
dyOptions(colors = RColorBrewer::brewer.pal(32, "Set2")):
Personaliza los colores de las series en el gráfico utilizando la paleta
de colores “Set2” de RColorBrewer, que proporciona una paleta de 32
colores.
dyHighlight(highlightSeriesOpts = list(strokeWidth = 2)):
Permite resaltar las series en el gráfico cuando el usuario pasa el
cursor sobre ellas. strokeWidth = 2 establece el grosor de
la línea resaltada a 2 píxeles.
G.Trabajo <- dygraph(ts.Trabajo, main = "Trabajo", ylab = "Migrantes", xlab = "Periodo") %>%
dyRangeSelector() %>%
dyLegend(width = 650) %>%
dyOptions(colors = RColorBrewer::brewer.pal(32, "Set2")) %>%
dyHighlight(highlightSeriesOpts = list(strokeWidth = 2))
G.Trabajo
A continuación, se presenta de manera desagregada un análisis
descriptivo de las 32 ciudades autorepresentadas.
Análisis descriptivo: Motivo de trabajo
| |
vars |
n |
mean |
sd |
median |
trimmed |
mad |
min |
max |
range |
skew |
kurtosis |
se |
| Centro_ACA_Trabajo |
1 |
60 |
3276.68 |
1229.07 |
3073.0 |
3128.54 |
704.24 |
1421 |
8076 |
6655 |
1.87 |
4.93 |
158.67 |
| Centro_CUER_Trabajo |
2 |
60 |
2076.98 |
799.35 |
2010.0 |
2008.62 |
685.70 |
778 |
4651 |
3873 |
0.89 |
0.92 |
103.20 |
| Centro_MEX_Trabajo |
3 |
60 |
36437.75 |
12699.62 |
35751.5 |
35338.75 |
11613.21 |
16225 |
76577 |
60352 |
0.84 |
0.93 |
1639.51 |
| Centro_PACH_Trabajo |
4 |
60 |
1328.42 |
393.88 |
1313.0 |
1305.79 |
378.06 |
452 |
2584 |
2132 |
0.60 |
0.75 |
50.85 |
| Centro_PUE_Trabajo |
5 |
60 |
3720.97 |
1334.62 |
3620.5 |
3623.44 |
1476.67 |
1687 |
8752 |
7065 |
0.99 |
1.76 |
172.30 |
| Centro_TOL_Trabajo |
6 |
60 |
1460.93 |
808.15 |
1252.0 |
1360.29 |
570.06 |
163 |
4234 |
4071 |
1.21 |
1.39 |
104.33 |
| Centro_TLAX_Trabajo |
7 |
60 |
2004.47 |
664.00 |
2004.5 |
1951.81 |
507.05 |
927 |
4742 |
3815 |
1.27 |
3.35 |
85.72 |
| Noreste_DUR_Trabajo |
8 |
60 |
1302.52 |
653.81 |
1226.0 |
1232.54 |
578.21 |
385 |
3742 |
3357 |
1.39 |
2.86 |
84.41 |
| Noreste_MTY_Trabajo |
9 |
60 |
6180.50 |
2139.86 |
5990.0 |
6042.71 |
1902.92 |
2373 |
12892 |
10519 |
0.67 |
0.64 |
276.25 |
| Noreste_SLP_Trabajo |
10 |
60 |
2271.88 |
1030.52 |
2066.0 |
2180.46 |
722.03 |
373 |
6524 |
6151 |
1.36 |
3.31 |
133.04 |
| Noreste_SLT_Trabajo |
11 |
60 |
1107.57 |
612.45 |
975.5 |
1039.02 |
415.13 |
219 |
4132 |
3913 |
2.53 |
9.51 |
79.07 |
| Noreste_TAM_Trabajo |
12 |
60 |
2560.93 |
753.01 |
2504.5 |
2490.02 |
526.32 |
1241 |
4933 |
3692 |
1.03 |
1.31 |
97.21 |
| Noroeste_CHIH_Trabajo |
13 |
60 |
1891.30 |
956.51 |
1845.0 |
1785.42 |
631.59 |
314 |
5577 |
5263 |
1.49 |
3.41 |
123.48 |
| Noroeste_CUL_Trabajo |
14 |
60 |
1369.95 |
619.08 |
1201.5 |
1265.06 |
447.75 |
616 |
3549 |
2933 |
1.52 |
2.16 |
79.92 |
| Noroeste_HER_Trabajo |
15 |
60 |
1761.20 |
691.17 |
1625.5 |
1666.98 |
418.83 |
721 |
4428 |
3707 |
1.81 |
4.22 |
89.23 |
| Noroeste_PAZ_Trabajo |
16 |
60 |
683.58 |
275.34 |
622.5 |
659.85 |
259.46 |
255 |
1334 |
1079 |
0.71 |
-0.29 |
35.55 |
| Noroeste_TIJ_Trabajo |
17 |
60 |
4250.72 |
1605.87 |
4250.0 |
4159.40 |
1555.25 |
971 |
8584 |
7613 |
0.53 |
0.46 |
207.32 |
| Occidente_AGS_Trabajo |
18 |
60 |
1253.98 |
545.25 |
1097.5 |
1197.27 |
352.86 |
310 |
3041 |
2731 |
1.21 |
1.66 |
70.39 |
| Occidente_COL_Trabajo |
19 |
60 |
839.73 |
261.77 |
804.0 |
821.60 |
284.66 |
346 |
1626 |
1280 |
0.64 |
-0.06 |
33.79 |
| Occidente_GDL_Trabajo |
20 |
60 |
6266.35 |
2037.18 |
6220.5 |
6153.10 |
1678.30 |
1689 |
13052 |
11363 |
0.68 |
1.26 |
263.00 |
| Occidente_LN_Trabajo |
21 |
60 |
1937.27 |
1153.90 |
1611.0 |
1738.67 |
679.03 |
692 |
7030 |
6338 |
2.39 |
7.01 |
148.97 |
| Occidente_MOR_Trabajo |
22 |
60 |
2327.93 |
679.93 |
2218.5 |
2288.12 |
617.50 |
1137 |
4755 |
3618 |
0.85 |
1.27 |
87.78 |
| Occidente_QRT_Trabajo |
23 |
60 |
2459.40 |
1041.07 |
2268.5 |
2339.35 |
876.96 |
903 |
5660 |
4757 |
1.04 |
0.89 |
134.40 |
| Occidente_TEP_Trabajo |
24 |
60 |
1445.45 |
443.35 |
1376.5 |
1401.23 |
381.77 |
687 |
2867 |
2180 |
0.90 |
0.64 |
57.24 |
| Occidente_ZAC_Trabajo |
25 |
60 |
535.97 |
243.95 |
488.5 |
510.15 |
176.43 |
154 |
1694 |
1540 |
1.93 |
6.56 |
31.49 |
| Sureste_CANC_Trabajo |
26 |
60 |
1909.12 |
681.59 |
1732.5 |
1866.08 |
613.80 |
814 |
4182 |
3368 |
0.79 |
0.70 |
87.99 |
| Sureste_CAMP_Trabajo |
27 |
60 |
400.65 |
178.63 |
362.0 |
386.21 |
151.97 |
84 |
968 |
884 |
0.84 |
0.68 |
23.06 |
| Sureste_MER_Trabajo |
28 |
60 |
1880.15 |
764.38 |
1789.0 |
1802.12 |
549.30 |
755 |
5452 |
4697 |
1.81 |
6.02 |
98.68 |
| Sureste_OAX_Trabajo |
29 |
60 |
1674.82 |
725.90 |
1590.5 |
1569.25 |
584.89 |
779 |
4725 |
3946 |
2.30 |
7.04 |
93.71 |
| Sureste_TGTZ_Trabajo |
30 |
60 |
1911.53 |
753.69 |
1651.0 |
1831.71 |
524.10 |
632 |
4188 |
3556 |
0.94 |
0.22 |
97.30 |
| Sureste_VER_Trabajo |
31 |
60 |
2038.40 |
720.73 |
1941.5 |
2015.21 |
700.53 |
364 |
3619 |
3255 |
0.20 |
-0.26 |
93.05 |
| Sureste_VH_Trabajo |
32 |
60 |
1181.52 |
398.62 |
1122.0 |
1151.38 |
348.41 |
339 |
2591 |
2252 |
0.90 |
1.44 |
51.46 |
Ejemplo: Por causas de trabajo la ciudad de Acapulco
muestra una media de 4.62 personas que emigraron por trabajo de cada
1000 personas.
Serie de tiempo jerárquica
Se utiliza la función hts para crear una serie de tiempo
jerárquica.
Definición de vectores:
Regiones: Un vector que contiene códigos de regiones
repetidos para crear una etiqueta de región específica.
Ciudades: Un vector que contiene códigos de ciudades
que se combinan con las regiones para crear nombres únicos.
Motivo: Un vector que contiene el motivo “Trabajo”,
repetido para igualar la longitud de los otros vectores.
Creacion del nombre de columnas
Se utilizan los datos de último nivel y se utiliza el argumento
characters donde los primeros dos caracteres corresponden
al primer nivel (Región), los siguientes dos corresponden
al segundo nivel (Ciudades) y como último los siete
caracteres corresponden al motivo de la ausencia
(Trabajo).
hts(ts.Trabajo, nodes = list(32), characters = c(2, 2, 7)):
Crea un modelo jerárquico de series temporales (hts) a
partir de ts.Trabajo.
nodes = list(32): Define un solo nivel en la jerarquía
(nivel 1) con 32 nodos.
characters = c(2, 2, 7): Define la estructura de los
nombres de las columnas en términos de caracteres para la
región(2), ciudad(2) y
motivo(7).
Modelo1$labels$Level 1 <- c("Centro", "Noreste", "Noroeste", "Sureste", "Occidente"):
Asigna etiquetas a los nodos en el nivel 1 del modelo Modelo1.
Estas etiquetas representan diferentes regiones o áreas geográficas en
lugar de los códigos originales.
#Cambiamos los nombres de las columnas
Regiones <- c(rep("CE", 7),
rep("NE", 5),
rep("NW", 5),
rep("WE", 8),
rep("SO", 7))
Ciudades <- c("11", "24", "01", "32", "04", "14", "29",
"21", "03", "06", "15", "09",
"08", "19", "20", "30", "18",
"12", "27", "02", "05", "13", "28", "22", "26",
"31", "23", "07", "25", "17", "10", "16")
Motivo <- c(rep("Trabajo", 32))
nombres <- paste0(Regiones, Ciudades, Motivo) ## Largo de 11 /Regiones=2,Ciudades=2,Motivo=7
colnames(ts.Trabajo) <- nombres
#Nodos
Modelo1 <- hts(ts.Trabajo, nodes = list(32), characters = c(2, 2, 7))
## Cambiamos las etiquetas
Modelo1$labels$`Level 1` <- c("Centro", "Noreste", "Noroeste", "Sureste", "Occidente")
[1] "hts" "gts"
Hierarchical Time Series
4 Levels
Number of nodes at each level: 1 5 32 32
Total number of series: 70
Number of observations per series: 57
Top level series:
Qtr1 Qtr2 Qtr3 Qtr4
2005 181720 221684 125424 85399
2006 93376 114025 114634 106325
2007 88853 122836 96359 90540
2008 84774 95417 97380 70266
2009 107129 118041 111815 76948
2010 80878 80668 72698 86746
2011 80383 94402 71951 80582
2012 103653 78282 89342 94176
2013 90291 84373 97686 81500
2014 97991 95923 102743 93418
2015 104140 103351 114061 102196
2016 108697 89450 106471 107005
2017 123622 97961 145247 99029
2018 98958 105396 109788 81128
2019 102746
Labels:
[1] "Level 0" "Level 1" "Level 2" "Level 3"
#p<-smatrix(Modelo1) #Resumen de la matriz de hierarquical time series
#q<-allts(Modelo1) #Matrix de todos los niveles
Nivel 1: Región
Se visualizan las series temporales agregadas de un modelo jerárquico
de series temporales (Modelo1).
aggts(level = 1): Extrae las series temporales
agregadas del nivel 1 del modelo Modelo1. El
level = 1indica que se está extrayendo datos del nivel más
alto en la jerarquía.
Modelo1 %>%
aggts(level = 1) %>%
autoplot(size = 1) +
theme_classic() +
theme(plot.title = element_text(size = 20),
plot.subtitle = element_text(size = 12),
legend.text = element_text(size = 8),
legend.key.size = unit(0.5, "lines")) +
scale_color_viridis_d() +
scale_color_manual(values = RColorBrewer::brewer.pal(5, "Dark2")) +
scale_x_continuous(breaks = seq(2005, 2019, by = 3)) +
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo",
y = "Rate",
x = "Year",
color = "Series")
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.

La gráfica superior muestra la tasa de migración por trabajo total
por región. Donde se puede apreciar que la región Noreste y Noroeste
presentan una menor moivilidad con respecto a las demás.
Nivel 2: Ciudad autorepresentada
A continuación se muetran los datos desglosados por las 32
ciudades.
aggts(level = 2): indica que se están extrayendo datos
de un nivel de jerarquía inferior al nivel 1.
Modelo1 %>%
aggts(level = 2) %>%
autoplot(size = 0.5) +
theme_classic() +
theme(plot.title = element_text(size = 20, family = "Century Gothic"),
plot.subtitle = element_text(size = 12, family = "Century Gothic"),
legend.text = element_text(size = 8, family = "Century Gothic"),
legend.spacing.x = unit(0.1, "cm"),
legend.key.size = unit(0.5, "lines"),
legend.position = "bottom") +
scale_color_manual(values = colorRampPalette(brewer.pal(8, "Dark2"))(60)) +
guides(col = guide_legend(ncol = 15)) +
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo",
y = "Rate",
x = "Year",
color = "Series")

Si bien la gráfica anterior no permite su interpretabilidad debido a
que todo el ensamble de las series están muy juntas.
Haciendo uso de la función aggts extrae las series
temporales de un objeto hts para cualquier nivel de
desagregación. Para aggts(Modelo1, level = 2), se
especifica que queremos extraer las series temporales del nivel 2 del
modelo jerárquico. Los niveles en un modelo jerárquico corresponden a
diferentes niveles de agregación en la jerarquía de datos.
Para este caso, se están trabajando con dos niveles de desagregación
(Regiones y Ciudades) y bien un Nivel Cero (Total).
groups <- aggts(Modelo1, level = 2)
En el siguiente gráfico se muestran las series de tiempo del nivel
inferior, es decir, las tasas de migración por trabajo para cada una de
las ciudades en sus respectivas regiones.
Ayudando así a visualizar de manera individual las series.
tibble::as_tibble(groups) %>%
tidyr::gather(Series) %>%
mutate(Date = rep(time(groups), NCOL(groups)),
Group = stringr::str_extract(Series, "([A-Za-z ]*)")) %>%
ggplot(aes(x = Date, y = value, group = Series, colour = Series)) +
geom_line() +
theme_classic() +
theme(plot.title = element_text(size = 20, family = "Century Gothic"),
plot.subtitle = element_text(size = 12, family = "Century Gothic"),
axis.text.x = element_text(angle = 90, hjust = 1, family = "Century Gothic"),
legend.text = element_text(size = 8, family = "Century Gothic"),
legend.spacing.x = unit(0.1, "cm"),
legend.key.size = unit(0.5, "lines"),
legend.position = "bottom") +
scale_color_viridis_d() +
#scale_color_manual(values = colorRampPalette(brewer.pal(8, "Set2"))(33)) +
scale_x_continuous(breaks = seq(1980, 2015, by = 5)) +
scale_y_continuous(labels = scales::comma) +
guides(col = guide_legend(ncol = 15)) +
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo",
y = "Rate",
x = "Year",
color = "Grupos") +
facet_wrap(. ~ Group)

Forecasting: Motivo de trabajo
Utilizando la función forecast() del paquete
hts.
Se presentan tres opciones integradas para producir pronósticos
usando el parámetro fmethod:
- ETS
Exponential Smoothing,
- Modelos
ARIMA
- Caminatas aleatorias(
RW).
Enfoques
Enfoque de abajo hacia arriba
“bottom-up”(method= "bu"): Pronostica del
nivel más bajo de la jerarquía, es decir, los motivos de ausencia y
luego va agregando los resultados a la jerárquía generar el pronostico
del nivel superior al último.
Enfoque de arriba hacia abajo
“top-down” (method= "tdfp"): Pronostica en
la jerarquía del nivel más alto, es decir, por regiones y luego va
desglosando los resultados en la jerarquía.
Enfoque intermedio **“middle-out”
(method= "mo"): Combina enfoques ascendentes y
descendentes. Primero, se elige un “nivel medio” y se generan
pronósticos para todas las series en este nivel. Para las series por
encima del nivel medio, se generan pronósticos coherentes utilizando el
enfoque de abajo hacia arriba agregando los pronósticos de “nivel medio”
hacia arriba. Para las series por debajo del “nivel medio”, se generan
pronósticos coherentes utilizando un enfoque de arriba hacia abajo al
desglosar los pronósticos de “nivel medio” hacia abajo.
method = "tdfp": Especifica el método de pronóstico
a utilizar. “tdfp” se refiere a “top-down forecasting using a detailed
forecast procedure”. Este método realiza el pronóstico a nivel más
detallado primero y luego agrega los pronósticos hacia los niveles
superiores de la jerarquía.
h = 4: Define el horizonte de pronóstico. En este
caso, se está pronosticando 4 períodos hacia el futuro.
keep.fitted = TRUE: Mantiene los valores ajustados
del modelo para su análisis posterior, lo cual puede ser útil para
evaluar el rendimiento del modelo.
#h<<-forecast horizon
#method= "mo"<<-"middle-out"
f.modelo1 <- forecast(Modelo1, h = 4, method = "tdfp", fmethod = "ets", parallel = TRUE, keep.fitted = TRUE)
[1] "hts" "gts"
Nivel 0 al 2
Se extraen las series temporales para los niveles 0, 1 y 2 tanto del
modelo de pronóstico (fcst1) como del modelo original
(groups). Esto te permitirá comparar los datos originales
con los pronósticos generados a diferentes niveles de la
jerarquía.
- levels = 0:2: Especifica que se deben extraer las series
temporales para los niveles 0, 1 y 2 del modelo jerárquico.
fcst1 <- aggts(f.modelo1, levels = 0:2)
groups <- aggts(Modelo1, levels = 0:2)
Se visualizan tanto las series temporales pronosticadas (fcst1) como
las series temporales originales (groups).
autoplot(fcst1, size = 0.5) +
autolayer(groups) +
geom_vline(xintercept = 2019, color = "#A8ABD7", linetype= "dashed") +
theme_classic() +
theme(plot.title = element_text(size = 18, family = "Century Gothic"),
plot.subtitle = element_text(size = 14, family = "Century Gothic"),
legend.text = element_text(size = 7, family = "Century Gothic"),
legend.key.size = unit(0.5, "lines"),
legend.position = "bottom") +
scale_color_viridis_d() +
scale_x_continuous(breaks = seq(2005, 2025, by = 2)) +
scale_y_continuous(labels = scales::comma) +
guides(col = guide_legend(ncol = 15))+
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo",
y = "Rate",
x = "Year",
color = "Series")
For a multivariate time series, specify a seriesname for each time series. Defaulting to column names.

Ahora bien, se combinan las series temporales originales y los
pronósticos en una sola serie temporal, manteniendo la misma frecuencia
y punto de partida que las series originales.
tabla <- ts(rbind(groups, fcst1), start = start(groups), frequency = 4)
Nivel Total: Por motivo de trabajo
A continuación se muetran los datos desglosados a nivel Nacional.
#http://www.sthda.com/english/wiki/ggplot2-line-types-how-to-change-line-types-of-a-graph-in-r-software
autoplot(tabla[, "Total"], colour = "#1720B7", size = 1.2, alpha = 0.6, linetype = "dashed") +
geom_vline(xintercept = 2019.5, color = "#A8ABD7", linetype = "dashed") +
theme_classic() +
scale_x_continuous(breaks = seq(2005, 2025, by = 2)) +
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo",
y = "Rate",
x = "Year",
color = "Series")
Scale for x is already present.
Adding another scale for x, which will replace the existing scale.

as_tibble(tabla[,-1]) %>%
tidyr::gather(Series) %>%
mutate(Date = rep(time(tabla), NCOL(tabla)-1),
Group = str_extract(Series, "([A-Za-z ]*)")) %>%
ggplot(aes(x = Date, y = value, group = Series, colour = Series)) +
geom_line() +
geom_vline(xintercept = 2017, color = "#A8ABD7", linetype = "dashed") +
theme_classic() +
theme(plot.title = element_text(size = 18, family = "Century Gothic"),
plot.subtitle = element_text(size = 14, family = "Century Gothic"),
axis.text.x = element_text(angle = 90, hjust = 1, family = "Century Gothic"),
legend.position = "bottom",
legend.text = element_text(size = 8, family = "Century Gothic"),
legend.key.size = unit(0.5, "lines")) +
scale_color_viridis_d() +
scale_x_continuous(breaks = seq(1985, 2025, by = 10)) +
guides(col = guide_legend(ncol = 15))+
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo",
y = "Rate",
x = "Year",
color = "Series") +
facet_wrap(.~Group)

Se extraen las series temporales para los niveles 0, 1 y 2 tanto del
modelo de pronóstico (f.modelo1). Esto te permitirá
comparar los datos originales con los pronósticos generados a diferentes
niveles de la jerarquía.
levels = 0:2: Especifica que se deben extraer las
series temporales para los niveles 0, 1 y 2 del modelo jerárquico.
f.modelo1 %>%
aggts(levels = 0:2) %>%
autoplot(facet = FALSE) +
theme_classic() +
theme(plot.title = element_text(size = 18, family = "Century Gothic"),
plot.subtitle = element_text(size = 14, family = "Century Gothic"),
legend.text = element_text(size = 7, family = "Century Gothic"),
legend.key.size = unit(0.5, "lines")) +
scale_color_viridis_d() +
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo",
y = "Rate",
x = "Year",
color = "Series")
Motivos de ausencia en general
Utilizando los 5 motivos de ausencia: - Trabajo
- Estudio
- Se casó o unió
- Se separó o divorció
- Reunirse con la familia
Serie de tiempo
Los datos de la estructura general se convierten en objetos de series
temporales (ts) utilizando la función ts. Cada
serie temporal se define con:
start = 2005: El primer año de la serie temporal es
2005.
end = 2019: El último año de la serie temporal es
2019.
frequency = 4: La frecuencia de la serie temporal es
trimestral (4 trimestres por año).
ts.mydata <- ts(mydata %>% select(., c(2:ncol(.))), start = 2005, end = 2019, frequency = 4)
Series de tiempo por motivos de la migración
Motivo de trabajo
G.Trabajo <- dygraph(ts.Trabajo, main = "Trabajo", ylab = "Migrantes", xlab = "Periodo") %>%
dyRangeSelector() %>%
dyLegend(width = 650) %>%
dyOptions(colors = RColorBrewer::brewer.pal(32, "Set2")) %>%
dyHighlight(highlightSeriesOpts = list(strokeWidth = 2))
G.Trabajo
Motivo de estudio
G.Estudio <- dygraph(ts.Estudio, main = "Estudio", ylab = "Migrantes", xlab = "Periodo") %>%
dyRangeSelector() %>%
dyLegend(width = 650) %>%
dyOptions(colors = RColorBrewer::brewer.pal(32, "Set2")) %>%
dyHighlight(highlightSeriesOpts = list(strokeWidth = 2))
G.Estudio
Analisis descriptivo: Estudio
| |
vars |
n |
mean |
sd |
median |
trimmed |
mad |
min |
max |
range |
skew |
kurtosis |
se |
| Centro_ACA_Estudio |
1 |
60 |
0.78 |
0.46 |
0.68 |
0.73 |
0.51 |
0.00 |
1.93 |
1.93 |
0.70 |
-0.22 |
0.06 |
| Centro_CUER_Estudio |
2 |
60 |
0.34 |
0.30 |
0.23 |
0.31 |
0.19 |
0.00 |
1.11 |
1.11 |
0.89 |
-0.30 |
0.04 |
| Centro_MEX_Estudio |
3 |
60 |
0.31 |
0.21 |
0.28 |
0.29 |
0.19 |
0.00 |
0.91 |
0.91 |
0.77 |
0.02 |
0.03 |
| Centro_PACH_Estudio |
4 |
60 |
1.01 |
0.54 |
0.94 |
0.96 |
0.46 |
0.23 |
2.89 |
2.65 |
1.10 |
1.95 |
0.07 |
| Centro_PUE_Estudio |
5 |
60 |
0.31 |
0.27 |
0.25 |
0.27 |
0.19 |
0.00 |
1.45 |
1.45 |
1.94 |
4.77 |
0.03 |
| Centro_TOL_Estudio |
6 |
60 |
0.24 |
0.18 |
0.21 |
0.22 |
0.15 |
0.00 |
0.76 |
0.76 |
0.95 |
0.60 |
0.02 |
| Centro_TLAX_Estudio |
7 |
60 |
0.55 |
0.36 |
0.52 |
0.52 |
0.36 |
0.00 |
1.55 |
1.55 |
0.74 |
-0.19 |
0.05 |
| Noreste_DUR_Estudio |
8 |
60 |
0.45 |
0.35 |
0.42 |
0.42 |
0.37 |
0.00 |
1.33 |
1.33 |
0.67 |
-0.42 |
0.04 |
| Noreste_MTY_Estudio |
9 |
60 |
0.36 |
0.19 |
0.34 |
0.35 |
0.20 |
0.00 |
0.94 |
0.94 |
0.66 |
0.27 |
0.02 |
| Noreste_SLP_Estudio |
10 |
60 |
0.46 |
0.30 |
0.42 |
0.44 |
0.29 |
0.00 |
1.25 |
1.25 |
0.51 |
-0.42 |
0.04 |
| Noreste_SLT_Estudio |
11 |
60 |
0.44 |
0.48 |
0.36 |
0.35 |
0.32 |
0.00 |
2.66 |
2.66 |
2.49 |
7.71 |
0.06 |
| Noreste_TAM_Estudio |
12 |
60 |
0.66 |
0.50 |
0.54 |
0.60 |
0.42 |
0.00 |
1.97 |
1.97 |
1.01 |
0.35 |
0.06 |
| Noroeste_CHIH_Estudio |
13 |
60 |
0.36 |
0.26 |
0.31 |
0.34 |
0.24 |
0.00 |
1.20 |
1.20 |
0.70 |
0.25 |
0.03 |
| Noroeste_CUL_Estudio |
14 |
60 |
0.54 |
0.31 |
0.52 |
0.54 |
0.36 |
0.00 |
1.19 |
1.19 |
0.10 |
-0.93 |
0.04 |
| Noroeste_HER_Estudio |
15 |
60 |
0.71 |
0.38 |
0.64 |
0.68 |
0.28 |
0.00 |
1.65 |
1.65 |
0.63 |
-0.16 |
0.05 |
| Noroeste_PAZ_Estudio |
16 |
60 |
1.12 |
0.55 |
1.07 |
1.08 |
0.54 |
0.16 |
2.39 |
2.22 |
0.45 |
-0.43 |
0.07 |
| Noroeste_TIJ_Estudio |
17 |
60 |
0.47 |
0.39 |
0.42 |
0.43 |
0.35 |
0.00 |
2.04 |
2.04 |
1.57 |
3.48 |
0.05 |
| Occidente_AGS_Estudio |
18 |
60 |
0.36 |
0.26 |
0.28 |
0.34 |
0.23 |
0.00 |
0.95 |
0.95 |
0.64 |
-0.34 |
0.03 |
| Occidente_COL_Estudio |
19 |
60 |
0.84 |
0.46 |
0.77 |
0.81 |
0.40 |
0.00 |
2.15 |
2.15 |
0.57 |
0.24 |
0.06 |
| Occidente_GDL_Estudio |
20 |
60 |
0.30 |
0.22 |
0.24 |
0.27 |
0.19 |
0.00 |
1.03 |
1.03 |
0.96 |
0.42 |
0.03 |
| Occidente_LN_Estudio |
21 |
60 |
0.23 |
0.18 |
0.18 |
0.21 |
0.14 |
0.00 |
0.72 |
0.72 |
0.85 |
0.18 |
0.02 |
| Occidente_MOR_Estudio |
22 |
60 |
0.59 |
0.41 |
0.56 |
0.56 |
0.45 |
0.00 |
1.64 |
1.64 |
0.53 |
-0.65 |
0.05 |
| Occidente_QRT_Estudio |
23 |
60 |
0.43 |
0.35 |
0.34 |
0.40 |
0.43 |
0.00 |
1.35 |
1.35 |
0.63 |
-0.35 |
0.04 |
| Occidente_TEP_Estudio |
24 |
60 |
0.88 |
0.42 |
0.82 |
0.86 |
0.37 |
0.00 |
2.10 |
2.10 |
0.45 |
0.50 |
0.05 |
| Occidente_ZAC_Estudio |
25 |
60 |
0.66 |
0.38 |
0.67 |
0.64 |
0.38 |
0.00 |
2.00 |
2.00 |
0.86 |
1.72 |
0.05 |
| Sureste_CANC_Estudio |
26 |
60 |
0.92 |
0.44 |
0.90 |
0.89 |
0.39 |
0.00 |
2.12 |
2.12 |
0.57 |
0.02 |
0.06 |
| Sureste_CAMP_Estudio |
27 |
60 |
0.44 |
0.29 |
0.39 |
0.43 |
0.31 |
0.00 |
1.33 |
1.33 |
0.59 |
0.16 |
0.04 |
| Sureste_MER_Estudio |
28 |
60 |
0.40 |
0.31 |
0.32 |
0.36 |
0.26 |
0.00 |
1.33 |
1.33 |
1.03 |
0.59 |
0.04 |
| Sureste_OAX_Estudio |
29 |
60 |
1.13 |
0.59 |
0.95 |
1.09 |
0.55 |
0.08 |
2.57 |
2.49 |
0.53 |
-0.57 |
0.08 |
| Sureste_TGTZ_Estudio |
30 |
60 |
0.65 |
0.35 |
0.61 |
0.63 |
0.31 |
0.00 |
1.60 |
1.60 |
0.58 |
-0.20 |
0.04 |
| Sureste_VER_Estudio |
31 |
60 |
0.40 |
0.33 |
0.33 |
0.37 |
0.28 |
0.00 |
1.25 |
1.25 |
0.64 |
-0.58 |
0.04 |
| Sureste_VH_Estudio |
32 |
60 |
0.97 |
0.53 |
0.85 |
0.93 |
0.44 |
0.13 |
2.29 |
2.16 |
0.63 |
-0.45 |
0.07 |
Motivo se unió o casó
G.Union <- dygraph(ts.Union, main = "Se unió o casó", ylab = "Migrantes", xlab = "Periodo") %>%
dyRangeSelector() %>%
dyLegend(width = 650) %>%
dyOptions(colors = RColorBrewer::brewer.pal(32, "Set2")) %>%
dyHighlight(highlightSeriesOpts = list(strokeWidth = 2))
G.Union
Analisis descriptivo: Se unió o casó
| |
vars |
n |
mean |
sd |
median |
trimmed |
mad |
min |
max |
range |
skew |
kurtosis |
se |
| Centro_ACA_Union |
1 |
60 |
1282.68 |
570.69 |
1244.0 |
1242.33 |
441.81 |
225 |
3951 |
3726 |
1.93 |
7.20 |
73.68 |
| Centro_CUER_Union |
2 |
60 |
1636.95 |
542.44 |
1712.0 |
1634.42 |
514.46 |
465 |
2925 |
2460 |
0.00 |
-0.60 |
70.03 |
| Centro_MEX_Union |
3 |
60 |
39873.95 |
12726.17 |
38255.5 |
38218.60 |
7503.44 |
22549 |
100291 |
77742 |
2.42 |
8.32 |
1642.94 |
| Centro_PACH_Union |
4 |
60 |
707.23 |
281.13 |
660.5 |
678.58 |
220.91 |
252 |
1543 |
1291 |
0.91 |
0.46 |
36.29 |
| Centro_PUE_Union |
5 |
60 |
4436.13 |
1357.04 |
4396.5 |
4361.19 |
1302.46 |
1726 |
7776 |
6050 |
0.44 |
-0.16 |
175.19 |
| Centro_TOL_Union |
6 |
60 |
2453.82 |
735.09 |
2475.5 |
2437.10 |
864.36 |
1122 |
4200 |
3078 |
0.14 |
-0.73 |
94.90 |
| Centro_TLAX_Union |
7 |
60 |
1537.23 |
585.80 |
1562.5 |
1475.52 |
352.12 |
571 |
4370 |
3799 |
2.25 |
8.29 |
75.63 |
| Noreste_DUR_Union |
8 |
60 |
1307.10 |
458.62 |
1202.0 |
1253.83 |
350.63 |
504 |
3378 |
2874 |
1.77 |
5.34 |
59.21 |
| Noreste_MTY_Union |
9 |
60 |
10975.08 |
2529.97 |
10741.0 |
10734.12 |
2431.46 |
7268 |
19391 |
12123 |
0.91 |
1.00 |
326.62 |
| Noreste_SLP_Union |
10 |
60 |
2435.90 |
909.59 |
2378.5 |
2385.60 |
943.67 |
938 |
4568 |
3630 |
0.36 |
-0.52 |
117.43 |
| Noreste_SLT_Union |
11 |
60 |
2186.33 |
671.94 |
2096.0 |
2125.79 |
478.88 |
850 |
4580 |
3730 |
1.07 |
2.05 |
86.75 |
| Noreste_TAM_Union |
12 |
60 |
1545.40 |
455.18 |
1489.5 |
1525.00 |
470.73 |
743 |
2624 |
1881 |
0.40 |
-0.64 |
58.76 |
| Noroeste_CHIH_Union |
13 |
60 |
2441.02 |
808.19 |
2353.5 |
2402.46 |
887.34 |
906 |
4877 |
3971 |
0.46 |
-0.02 |
104.34 |
| Noroeste_CUL_Union |
14 |
60 |
2049.72 |
858.11 |
1933.5 |
1935.33 |
650.12 |
679 |
5546 |
4867 |
2.05 |
5.86 |
110.78 |
| Noroeste_HER_Union |
15 |
60 |
1948.65 |
578.75 |
1914.5 |
1899.52 |
617.50 |
995 |
3709 |
2714 |
0.84 |
0.45 |
74.72 |
| Noroeste_PAZ_Union |
16 |
60 |
561.07 |
212.86 |
539.5 |
549.96 |
230.54 |
92 |
1372 |
1280 |
0.85 |
1.98 |
27.48 |
| Noroeste_TIJ_Union |
17 |
60 |
4458.73 |
1450.91 |
4398.5 |
4373.35 |
1598.98 |
1498 |
8456 |
6958 |
0.42 |
-0.21 |
187.31 |
| Occidente_AGS_Union |
18 |
60 |
2061.78 |
568.70 |
2010.0 |
2018.54 |
505.57 |
1044 |
3739 |
2695 |
0.81 |
0.94 |
73.42 |
| Occidente_COL_Union |
19 |
60 |
718.90 |
273.00 |
656.5 |
681.00 |
216.46 |
367 |
1949 |
1582 |
2.02 |
5.92 |
35.24 |
| Occidente_GDL_Union |
20 |
60 |
10166.35 |
2742.03 |
9626.0 |
9980.56 |
2641.99 |
5099 |
17555 |
12456 |
0.62 |
-0.09 |
353.99 |
| Occidente_LN_Union |
21 |
60 |
3688.92 |
1022.98 |
3420.0 |
3580.40 |
781.33 |
2193 |
7331 |
5138 |
1.34 |
2.51 |
132.07 |
| Occidente_MOR_Union |
22 |
60 |
1299.08 |
443.28 |
1241.5 |
1259.42 |
398.82 |
503 |
2608 |
2105 |
0.80 |
0.63 |
57.23 |
| Occidente_QRT_Union |
23 |
60 |
1908.12 |
574.76 |
1864.5 |
1873.08 |
449.97 |
840 |
3499 |
2659 |
0.54 |
0.35 |
74.20 |
| Occidente_TEP_Union |
24 |
60 |
880.67 |
284.71 |
813.5 |
862.71 |
279.47 |
274 |
1594 |
1320 |
0.49 |
-0.42 |
36.76 |
| Occidente_ZAC_Union |
25 |
60 |
642.15 |
200.61 |
648.0 |
632.23 |
197.19 |
203 |
1239 |
1036 |
0.54 |
0.58 |
25.90 |
| Sureste_CANC_Union |
26 |
60 |
1461.20 |
440.96 |
1511.0 |
1449.60 |
438.85 |
591 |
2779 |
2188 |
0.33 |
0.20 |
56.93 |
| Sureste_CAMP_Union |
27 |
60 |
535.78 |
171.84 |
557.0 |
539.90 |
199.41 |
126 |
848 |
722 |
-0.26 |
-0.71 |
22.18 |
| Sureste_MER_Union |
28 |
60 |
2085.75 |
634.06 |
2066.0 |
2084.00 |
621.95 |
640 |
3393 |
2753 |
-0.04 |
-0.61 |
81.86 |
| Sureste_OAX_Union |
29 |
60 |
846.75 |
309.65 |
783.0 |
815.81 |
235.73 |
380 |
1905 |
1525 |
1.30 |
2.46 |
39.98 |
| Sureste_TGTZ_Union |
30 |
60 |
1283.23 |
419.63 |
1244.5 |
1284.33 |
355.82 |
401 |
2357 |
1956 |
0.14 |
-0.10 |
54.17 |
| Sureste_VER_Union |
31 |
60 |
1219.13 |
426.36 |
1204.0 |
1193.67 |
454.42 |
248 |
2338 |
2090 |
0.44 |
-0.09 |
55.04 |
| Sureste_VH_Union |
32 |
60 |
940.82 |
380.79 |
931.5 |
921.27 |
297.26 |
111 |
2415 |
2304 |
1.21 |
3.64 |
49.16 |
Motivo se dicorció o separó
G.Divorcio <- dygraph(ts.Divorcio, main = "Se dicorció o separó", ylab = "Migrantes", xlab = "Periodo") %>%
dyRangeSelector() %>%
dyLegend(width = 650) %>%
dyOptions(colors = RColorBrewer::brewer.pal(32, "Set2")) %>%
dyHighlight(highlightSeriesOpts = list(strokeWidth = 2))
G.Divorcio
Analisis descriptivo: Se separó o divorció
| |
vars |
n |
mean |
sd |
median |
trimmed |
mad |
min |
max |
range |
skew |
kurtosis |
se |
| Centro_ACA_Divorcio |
1 |
60 |
1.28 |
0.60 |
1.28 |
1.25 |
0.51 |
0.00 |
3.56 |
3.56 |
0.71 |
2.06 |
0.08 |
| Centro_CUER_Divorcio |
2 |
60 |
1.18 |
0.54 |
1.13 |
1.16 |
0.51 |
0.15 |
2.43 |
2.28 |
0.27 |
-0.58 |
0.07 |
| Centro_MEX_Divorcio |
3 |
60 |
1.24 |
0.41 |
1.15 |
1.21 |
0.33 |
0.55 |
2.71 |
2.16 |
0.98 |
1.29 |
0.05 |
| Centro_PACH_Divorcio |
4 |
60 |
1.31 |
0.61 |
1.20 |
1.28 |
0.64 |
0.24 |
3.08 |
2.85 |
0.43 |
-0.21 |
0.08 |
| Centro_PUE_Divorcio |
5 |
60 |
1.15 |
0.40 |
1.14 |
1.14 |
0.39 |
0.35 |
2.20 |
1.85 |
0.29 |
-0.15 |
0.05 |
| Centro_TOL_Divorcio |
6 |
60 |
1.36 |
0.58 |
1.27 |
1.33 |
0.57 |
0.42 |
3.20 |
2.78 |
0.60 |
0.38 |
0.07 |
| Centro_TLAX_Divorcio |
7 |
60 |
1.11 |
0.47 |
1.08 |
1.09 |
0.43 |
0.14 |
2.17 |
2.04 |
0.44 |
-0.36 |
0.06 |
| Noreste_DUR_Divorcio |
8 |
60 |
1.30 |
0.52 |
1.21 |
1.29 |
0.47 |
0.13 |
2.53 |
2.40 |
0.27 |
-0.59 |
0.07 |
| Noreste_MTY_Divorcio |
9 |
60 |
1.29 |
0.43 |
1.30 |
1.28 |
0.43 |
0.42 |
2.89 |
2.46 |
0.54 |
1.41 |
0.06 |
| Noreste_SLP_Divorcio |
10 |
60 |
1.07 |
0.42 |
1.04 |
1.04 |
0.27 |
0.26 |
2.92 |
2.66 |
1.66 |
5.47 |
0.05 |
| Noreste_SLT_Divorcio |
11 |
60 |
1.23 |
0.47 |
1.27 |
1.23 |
0.44 |
0.21 |
2.41 |
2.20 |
0.09 |
-0.13 |
0.06 |
| Noreste_TAM_Divorcio |
12 |
60 |
1.20 |
0.39 |
1.17 |
1.19 |
0.37 |
0.37 |
2.09 |
1.71 |
0.21 |
-0.48 |
0.05 |
| Noroeste_CHIH_Divorcio |
13 |
60 |
1.44 |
0.53 |
1.50 |
1.43 |
0.51 |
0.33 |
2.89 |
2.55 |
0.21 |
-0.31 |
0.07 |
| Noroeste_CUL_Divorcio |
14 |
60 |
1.39 |
0.54 |
1.30 |
1.35 |
0.55 |
0.53 |
3.31 |
2.78 |
0.86 |
1.10 |
0.07 |
| Noroeste_HER_Divorcio |
15 |
60 |
1.51 |
0.62 |
1.47 |
1.50 |
0.71 |
0.26 |
3.02 |
2.76 |
0.11 |
-0.46 |
0.08 |
| Noroeste_PAZ_Divorcio |
16 |
60 |
1.55 |
0.63 |
1.54 |
1.53 |
0.56 |
0.33 |
3.23 |
2.90 |
0.41 |
0.15 |
0.08 |
| Noroeste_TIJ_Divorcio |
17 |
60 |
1.84 |
0.69 |
1.80 |
1.82 |
0.66 |
0.39 |
3.30 |
2.91 |
0.15 |
-0.57 |
0.09 |
| Occidente_AGS_Divorcio |
18 |
60 |
0.91 |
0.40 |
0.88 |
0.91 |
0.48 |
0.21 |
1.79 |
1.58 |
0.06 |
-1.00 |
0.05 |
| Occidente_COL_Divorcio |
19 |
60 |
1.62 |
0.71 |
1.48 |
1.54 |
0.50 |
0.55 |
4.25 |
3.70 |
1.44 |
2.85 |
0.09 |
| Occidente_GDL_Divorcio |
20 |
60 |
1.12 |
0.39 |
1.01 |
1.11 |
0.34 |
0.27 |
2.32 |
2.05 |
0.42 |
0.12 |
0.05 |
| Occidente_LN_Divorcio |
21 |
60 |
0.97 |
0.37 |
0.92 |
0.96 |
0.35 |
0.24 |
1.96 |
1.72 |
0.44 |
-0.22 |
0.05 |
| Occidente_MOR_Divorcio |
22 |
60 |
1.04 |
0.45 |
0.98 |
1.02 |
0.39 |
0.19 |
2.27 |
2.08 |
0.54 |
-0.14 |
0.06 |
| Occidente_QRT_Divorcio |
23 |
60 |
0.89 |
0.38 |
0.87 |
0.86 |
0.34 |
0.34 |
2.52 |
2.19 |
1.36 |
3.99 |
0.05 |
| Occidente_TEP_Divorcio |
24 |
60 |
1.41 |
0.49 |
1.46 |
1.42 |
0.47 |
0.23 |
2.48 |
2.25 |
-0.23 |
-0.31 |
0.06 |
| Occidente_ZAC_Divorcio |
25 |
60 |
1.05 |
0.41 |
1.03 |
1.05 |
0.41 |
0.00 |
1.95 |
1.95 |
-0.06 |
-0.44 |
0.05 |
| Sureste_CANC_Divorcio |
26 |
60 |
1.75 |
0.63 |
1.75 |
1.73 |
0.74 |
0.66 |
3.05 |
2.39 |
0.17 |
-1.07 |
0.08 |
| Sureste_CAMP_Divorcio |
27 |
60 |
1.49 |
0.47 |
1.45 |
1.49 |
0.49 |
0.42 |
2.45 |
2.04 |
0.12 |
-0.67 |
0.06 |
| Sureste_MER_Divorcio |
28 |
60 |
1.25 |
0.51 |
1.23 |
1.25 |
0.54 |
0.27 |
2.21 |
1.94 |
0.07 |
-0.94 |
0.07 |
| Sureste_OAX_Divorcio |
29 |
60 |
0.87 |
0.38 |
0.87 |
0.85 |
0.37 |
0.17 |
1.85 |
1.68 |
0.31 |
-0.26 |
0.05 |
| Sureste_TGTZ_Divorcio |
30 |
60 |
1.62 |
0.59 |
1.63 |
1.59 |
0.60 |
0.53 |
3.55 |
3.03 |
0.65 |
0.52 |
0.08 |
| Sureste_VER_Divorcio |
31 |
60 |
1.56 |
0.67 |
1.46 |
1.51 |
0.65 |
0.13 |
3.41 |
3.28 |
0.59 |
-0.05 |
0.09 |
| Sureste_VH_Divorcio |
32 |
60 |
1.72 |
0.63 |
1.63 |
1.67 |
0.56 |
0.70 |
4.32 |
3.62 |
1.26 |
3.22 |
0.08 |
Motivo para reunirse con un familiar
G.Familiar <- dygraph(ts.Familia, main = "Reunirse con un familiar", ylab = "Migrantes", xlab = "Periodo") %>%
dyRangeSelector() %>%
dyLegend(width = 650) %>%
dyOptions(colors = RColorBrewer::brewer.pal(32, "Set2")) %>%
dyHighlight(highlightSeriesOpts = list(strokeWidth = 2))
G.Familiar
Analisis descriptivo: Reunirse con un familiar
| |
vars |
n |
mean |
sd |
median |
trimmed |
mad |
min |
max |
range |
skew |
kurtosis |
se |
| Centro_ACA_Familiar |
1 |
60 |
7.97 |
2.24 |
7.79 |
7.85 |
1.66 |
2.82 |
15.71 |
12.89 |
0.74 |
1.74 |
0.29 |
| Centro_CUER_Familiar |
2 |
60 |
4.42 |
2.38 |
4.49 |
4.33 |
2.29 |
0.54 |
9.87 |
9.33 |
0.18 |
-0.69 |
0.31 |
| Centro_MEX_Familiar |
3 |
60 |
3.92 |
1.02 |
4.02 |
3.93 |
1.08 |
1.30 |
5.86 |
4.55 |
-0.20 |
-0.38 |
0.13 |
| Centro_PACH_Familiar |
4 |
60 |
4.08 |
1.49 |
4.22 |
4.09 |
1.09 |
1.08 |
7.66 |
6.58 |
0.01 |
-0.07 |
0.19 |
| Centro_PUE_Familiar |
5 |
60 |
3.50 |
0.95 |
3.38 |
3.43 |
0.82 |
1.58 |
6.61 |
5.03 |
0.88 |
1.27 |
0.12 |
| Centro_TOL_Familiar |
6 |
60 |
3.73 |
1.42 |
3.51 |
3.69 |
1.61 |
1.24 |
7.12 |
5.89 |
0.29 |
-0.65 |
0.18 |
| Centro_TLAX_Familiar |
7 |
60 |
3.64 |
1.16 |
3.44 |
3.55 |
1.05 |
1.33 |
6.86 |
5.53 |
0.65 |
0.32 |
0.15 |
| Noreste_DUR_Familiar |
8 |
60 |
5.50 |
1.75 |
5.11 |
5.38 |
1.75 |
2.21 |
10.57 |
8.36 |
0.58 |
-0.19 |
0.23 |
| Noreste_MTY_Familiar |
9 |
60 |
5.81 |
2.83 |
5.87 |
5.79 |
4.01 |
1.03 |
11.21 |
10.18 |
-0.01 |
-1.19 |
0.36 |
| Noreste_SLP_Familiar |
10 |
60 |
5.14 |
1.67 |
5.20 |
5.15 |
1.85 |
1.96 |
7.96 |
6.00 |
-0.03 |
-1.06 |
0.22 |
| Noreste_SLT_Familiar |
11 |
60 |
6.73 |
1.81 |
6.69 |
6.78 |
1.69 |
3.02 |
10.71 |
7.69 |
-0.14 |
-0.52 |
0.23 |
| Noreste_TAM_Familiar |
12 |
60 |
5.93 |
1.83 |
5.82 |
5.78 |
1.38 |
2.81 |
12.20 |
9.39 |
1.15 |
2.31 |
0.24 |
| Noroeste_CHIH_Familiar |
13 |
60 |
5.39 |
1.33 |
5.32 |
5.38 |
1.49 |
2.60 |
8.93 |
6.33 |
0.20 |
-0.31 |
0.17 |
| Noroeste_CUL_Familiar |
14 |
60 |
7.48 |
2.01 |
7.02 |
7.28 |
1.94 |
4.08 |
12.97 |
8.89 |
0.81 |
0.23 |
0.26 |
| Noroeste_HER_Familiar |
15 |
60 |
6.73 |
2.08 |
6.33 |
6.56 |
1.84 |
3.06 |
13.30 |
10.24 |
0.83 |
0.63 |
0.27 |
| Noroeste_PAZ_Familiar |
16 |
60 |
5.87 |
1.79 |
5.76 |
5.85 |
1.54 |
1.79 |
10.12 |
8.33 |
0.11 |
-0.18 |
0.23 |
| Noroeste_TIJ_Familiar |
17 |
60 |
8.98 |
2.37 |
9.15 |
9.13 |
2.51 |
3.33 |
13.06 |
9.73 |
-0.50 |
-0.61 |
0.31 |
| Occidente_AGS_Familiar |
18 |
60 |
3.50 |
1.36 |
3.45 |
3.37 |
1.32 |
1.35 |
8.46 |
7.11 |
1.04 |
1.71 |
0.18 |
| Occidente_COL_Familiar |
19 |
60 |
4.09 |
2.17 |
3.85 |
3.89 |
1.97 |
1.03 |
13.38 |
12.35 |
1.46 |
3.93 |
0.28 |
| Occidente_GDL_Familiar |
20 |
60 |
5.16 |
1.50 |
5.09 |
5.17 |
1.39 |
1.58 |
9.28 |
7.70 |
0.15 |
0.35 |
0.19 |
| Occidente_LN_Familiar |
21 |
60 |
3.62 |
1.19 |
3.55 |
3.57 |
1.37 |
1.19 |
6.32 |
5.13 |
0.24 |
-0.65 |
0.15 |
| Occidente_MOR_Familiar |
22 |
60 |
3.80 |
1.25 |
3.71 |
3.72 |
1.15 |
1.56 |
7.03 |
5.48 |
0.54 |
-0.09 |
0.16 |
| Occidente_QRT_Familiar |
23 |
60 |
4.28 |
1.46 |
4.18 |
4.27 |
1.45 |
1.42 |
7.78 |
6.36 |
0.12 |
-0.34 |
0.19 |
| Occidente_TEP_Familiar |
24 |
60 |
5.64 |
2.05 |
5.63 |
5.52 |
1.93 |
1.89 |
10.96 |
9.07 |
0.49 |
-0.21 |
0.26 |
| Occidente_ZAC_Familiar |
25 |
60 |
4.88 |
1.32 |
4.63 |
4.86 |
1.30 |
2.26 |
7.71 |
5.45 |
0.24 |
-0.75 |
0.17 |
| Sureste_CANC_Familiar |
26 |
60 |
7.87 |
2.31 |
7.93 |
7.79 |
2.65 |
3.51 |
14.35 |
10.84 |
0.28 |
-0.41 |
0.30 |
| Sureste_CAMP_Familiar |
27 |
60 |
6.17 |
1.78 |
5.98 |
6.08 |
1.72 |
2.58 |
10.28 |
7.70 |
0.36 |
-0.33 |
0.23 |
| Sureste_MER_Familiar |
28 |
60 |
4.56 |
1.57 |
4.36 |
4.48 |
1.60 |
1.21 |
9.50 |
8.29 |
0.62 |
0.95 |
0.20 |
| Sureste_OAX_Familiar |
29 |
60 |
4.33 |
1.47 |
4.21 |
4.22 |
1.22 |
1.66 |
10.32 |
8.66 |
1.14 |
2.92 |
0.19 |
| Sureste_TGTZ_Familiar |
30 |
60 |
6.23 |
1.70 |
6.12 |
6.18 |
1.70 |
2.89 |
11.28 |
8.39 |
0.40 |
0.04 |
0.22 |
| Sureste_VER_Familiar |
31 |
60 |
4.13 |
1.60 |
3.89 |
4.07 |
1.84 |
0.91 |
7.78 |
6.87 |
0.27 |
-0.55 |
0.21 |
| Sureste_VH_Familiar |
32 |
60 |
6.81 |
1.98 |
6.71 |
6.74 |
2.11 |
3.21 |
12.45 |
9.24 |
0.43 |
-0.20 |
0.26 |
Modelo jerárquico
Se utiliza la función hts() para crear una serie de
tiempo jerárquica.
Donde se utilizan los datos de último nivel y se utiliza el argumento
characters donde los primeros dos caracteres corresponden
al primer nivel (Región), los siguientes dos corresponden al segundo
nivel (Ciudades) y como último los tres caracteres corresponden al
motivo de la ausencia.
TRA = “Trabajo”
EST = “Estudio”
UNI = “Se casó o unió”
DIV = “Se divorció o separó”
FAM = “Reunirse con un familiar”
Definición de vectores:
Regiones: Un vector que contiene códigos de regiones
repetidos para crear una etiqueta de región específica.
Ciudades: Un vector que contiene códigos de ciudades
que se combinan con las regiones para crear nombres únicos.
Motivo: Un vector que contiene el motivo de la
ausencia, repetido para igualar la longitud de los otros vectores.
Regiones <- rep(c(rep("CE", 7),
rep("NE", 5),
rep("NW", 5),
rep("WE", 8),
rep("SO", 7)), 5)
Ciudades <- rep(c("11", "24", "01", "32", "04", "14", "29",
"21", "03", "06", "15", "09",
"08", "19", "20", "30", "18",
"12", "27", "02", "05", "13", "28", "22", "26",
"31", "23", "07", "25", "17", "10", "16"), 5)
Motivo <- c(rep("TRA", 32),
rep("EST", 32),
rep("UNI", 32),
rep("DIV", 32),
rep("FAM", 32))
nombres <- paste0(Regiones, Ciudades, Motivo) #Largo de 7 | Regiones=2|Ciudades=2|Motivo=3
colnames(ts.mydata) <- nombres
nodes <- list(160, c(5, 32, 5)) #160 variables |Regiones=5|Ciudades=32|Motivos=5|
Modelo2 <- hts(ts.mydata, nodes = nodes,characters = c(2, 2, 3))
#Cambiamos los labels
Modelo2$labels$`Level 1` <- c("Centro", "Noreste", "Noroeste", "Sureste", "Occidente")
Nivel 1: Región
Se visualizan las series temporales agregadas de un modelo jerárquico
de series temporales (Modelo1).
aggts(level = 1): Extrae las series temporales
agregadas del nivel 1 del modelo Modelo1. El
level = 1indica que se está extrayendo datos del nivel más
alto en la jerarquía.
Modelo2 %>%
aggts(level = 1) %>%
autoplot(size = 1) +
theme_classic() +
theme(plot.title = element_text(size = 20),
plot.subtitle = element_text(size = 12),
legend.text = element_text(size = 8),
legend.key.size = unit(0.2, "cm")) +
scale_color_viridis_d() +
scale_color_manual(values = RColorBrewer::brewer.pal(5, "Dark2")) +
scale_x_continuous(breaks = seq(2005, 2019, by = 2)) +
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
y = "Rate",
x = "Year",
color = "Series")
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.

Nivel 2: Cuidad autorepresentada
A continuación se muetran los datos desglosados por las 32
ciudades.
aggts(level = 2): indica que se están extrayendo datos
de un nivel de jerarquía inferior al nivel 1.
Modelo2 %>%
aggts(level = 2) %>%
autoplot(size = 0.5) +
theme_classic() +
theme(plot.title = element_text(size = 20),
plot.subtitle = element_text(size = 12),
legend.text = element_text(size = 8),
legend.key.size = unit(0.5, "lines"),
legend.position = "bottom") +
scale_color_manual(values = colorRampPalette(brewer.pal(8, "Dark2"))(60)) +
guides(col = guide_legend(ncol = 15))+
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
y = "Rate",
x = "Year",
color = "Series")

Si bien la gráfica anterior no permite su interpretabilidad debido a
que todo el ensamble de las series están muy juntas.
Haciendo uso de la función aggts extrae las series
temporales de un objeto hts para cualquier nivel de
desagregación. Para aggts(Modelo1, level = 2), se
especifica que queremos extraer las series temporales del nivel 2 del
modelo jerárquico. Los niveles en un modelo jerárquico corresponden a
diferentes niveles de agregación en la jerarquía de datos.
Para este caso, se están trabajando con dos niveles de desagregación
(Regiones y Ciudades) y bien un Nivel Cero (Total).
groups <- aggts(Modelo2, level = 2)
tibble::as_tibble(groups) %>%
tidyr::gather(Series) %>%
mutate(Date = rep(time(groups), NCOL(groups)),
Group =stringr::str_extract(Series, "([A-Za-z ]*)")) %>%
ggplot(aes(x = Date, y = value, group = Series, colour = Series)) +
geom_line() +
theme_classic() +
theme(plot.title = element_text(size = 20),
plot.subtitle = element_text(size = 12),
axis.text.x = element_text(angle = 90, hjust = 1),
legend.text = element_text(size = 8),
legend.key.size = unit(0.5, "lines"),
legend.position = "bottom") +
scale_color_viridis_d() +
#scale_color_manual(values = colorRampPalette(brewer.pal(8, "Dark2"))(33)) +
scale_x_continuous(breaks = seq(1980, 2015, by = 5)) +
scale_y_continuous(labels = scales::comma) +
guides(col = guide_legend(ncol = 15))+
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
y = "Rate",
x = "Year",
color = "Series") +
facet_wrap(. ~ Group)

Nivel 3: Motivo de la ausencia
Haciendo uso de la función aggts extrae las series
temporales de un objeto hts para cualquier nivel de
desagregación. Para aggts(Modelo2, level = 3), se
especifica que queremos extraer las series temporales del nivel 23 del
modelo jerárquico. Los niveles en un modelo jerárquico corresponden a
diferentes niveles de agregación en la jerarquía de datos.
En modelo general, se están trabajando con tres niveles de
desagregación (Motivo de ausencia, Regiones y
Ciudades) y bien un Nivel Cero (Total).
groups <- aggts(Modelo2, level = 3)
#https://stringr.tidyverse.org/reference/str_locate.html
tibble::as_tibble(groups) %>%
tidyr::gather(Series) %>%
mutate(Date = rep(time(groups), NCOL(groups)),
Group =stringr::str_extract(Series, "([A-Za-z ]*)"),
Motivo=stringr::str_sub(Series,5, 7)) %>%
ggplot(aes(x = Date, y = value, group = Series, colour = Series)) +
geom_line() +
theme_classic() +
theme(plot.title = element_text(size = 20),
plot.subtitle = element_text(size = 12),
axis.text.x = element_text(angle = 90, hjust = 1),
legend.text = element_text(size = 8),
legend.key.width=unit(0.2, "cm"),
legend.key.height = unit(0, "cm"),
legend.spacing.x = unit(0, "cm"),
legend.key.size = unit(0.5, "lines"),
legend.position = "bottom") +
scale_color_viridis_d() +
#scale_color_manual(values = colorRampPalette(brewer.pal(8, "Dark2"))(160)) +
scale_x_continuous(breaks = seq(1980, 2015, by = 5)) +
scale_y_continuous(labels = scales::comma) +
guides(col = guide_legend(ncol = 15))+
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
y = "Rate",
x = "Year",
color = "Series") +
facet_wrap(. ~ Group + Motivo)

Analizando la gráfica anterior el motivo de ausencia para “Reunirse
con un familiar” es la que presenta un mayor número de casos
migratorios” con respecto a los otros cuatro casos.
#print(Modelo2)
#smatrix(Modelo2)
#allts(Modelo2)
Forecasting: Motivo de la ausencia en general
Se realiza un pronóstico jerárquico sobre Modelo2 para
los próximos 10 periodos, utilizando el método de
"middle-out" para la agregación jerárquica y el modelo
ARIMA para los pronósticos individuales.
Se espera que los pronósticos sean consistentes con la estructura de
agregación de las series de tiempo al agruparlas.
#h=forescast horizon
#method<-"mo", "bu", "tdfp"
f.modelo2 <- forecast(Modelo2, h = 10, method = "mo", level = 2, fmethod = "arima", parallel = TRUE, keep.fitted = TRUE)
Nivel 0 al 2: Total / Región / Ciudad
Se extraen las series temporales para los niveles 0, 1 y 2 tanto del
modelo de pronóstico (fcst2) como del modelo original
(groups). Esto te permitirá comparar los datos originales
con los pronósticos generados a diferentes niveles de la
jerarquía.
- levels = 0:2: Especifica que se deben extraer las series
temporales para los niveles 0, 1 y 2 del modelo jerárquico.
fcst2 <- aggts(f.modelo2, levels = 0:2)
groups <- aggts(Modelo2, levels = 0:2)
autoplot(fcst2, size = 0.5) +
autolayer(groups) +
geom_vline(xintercept = 2019,color = "#A8ABD7", linetype = "dashed") +
theme_classic() +
theme(plot.title = element_text(size = 20),
plot.subtitle = element_text(size = 12),
legend.text = element_text(size = 7),
legend.key.size = unit(0.5, "lines"),
legend.position = "bottom") +
scale_color_viridis_d() +
scale_x_continuous(breaks = seq(2005, 2025, by = 2)) +
scale_y_continuous(labels = scales::comma) +
guides(col = guide_legend(ncol = 15))+
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
y = "Rate",
x = "Year",
color = "Series")
For a multivariate time series, specify a seriesname for each time series. Defaulting to column names.

Se crea una serie temporal combinada de las series temporales
originales y los pronósticos.
tabla <- ts(rbind(groups, fcst2),
start = start(groups), frequency = 4) #Frecuencia al año
Nivel 0: Total de casos de migración
A continuación se muetran los datos desglosados a nivel Nacional.
#http://www.sthda.com/english/wiki/ggplot2-line-types-how-to-change-line-types-of-a-graph-in-r-software
autoplot(tabla[, "Total"], colour = "#1720B7", size = 1.2, alpha = 0.6, linetype = "dashed") +
geom_vline(xintercept=2019.5,color = "#A8ABD7",linetype= "dashed") +
theme_classic() +
theme(plot.title = element_text(size = 20),
plot.subtitle = element_text(size = 12)) +
scale_x_continuous(breaks = seq(2005, 2025, by = 2)) +
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
y = "Rate",
x = "Year",
color = "Series")
Scale for x is already present.
Adding another scale for x, which will replace the existing scale.

Nivel 1 a 2: Nivel región y nivel ciudad
A continuación se muetran los datos desglosados a nivel Región.
as_tibble(tabla[,-1]) %>%
tidyr::gather(Series) %>%
mutate(Date = rep(time(tabla), NCOL(tabla)-1),
Group = str_extract(Series, "([A-Za-z ]*)")) %>%
ggplot(aes(x = Date, y = value, group = Series, colour = Series)) +
geom_line() +
geom_vline(xintercept = 2019,color = "#A8ABD7", linetype = "dashed") +
theme_classic() +
theme(plot.title = element_text(size = 20),
plot.subtitle = element_text(size = 12),
axis.text.x = element_text(angle = 90, hjust = 1),
legend.text = element_text(size = 8),
legend.key.width = unit(0.2, "cm"),
legend.key.height = unit(0, "cm"),
legend.spacing.x = unit(0.1, "cm"),
legend.key.size = unit(0.5, "lines"),
legend.position = "bottom") +
scale_color_viridis_d() +
scale_x_continuous(breaks = seq(2005, 2025,by = 5)) +
guides(col = guide_legend(ncol = 15)) +
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
y = "Rate",
x = "Year",
color = "Series") +
facet_wrap(. ~ Group)

Nivel 3: Motivos de ausencia en general v
A continuación se muetran los datos desglosados por motivo de la
ausencia.
fcst3 <- aggts(f.modelo2, levels = 3)
groups <- aggts(Modelo2, levels = 3)
tabla <- ts(rbind(groups, fcst3), start = start(groups), frequency = 4) #Frecuencia al año
as_tibble(tabla[,-1]) %>%
tidyr::gather(Series) %>%
mutate(Date = rep(time(tabla), NCOL(tabla) - 1),
Group = str_extract(Series, "([A-Za-z ]*)"),
Motivo = stringr::str_sub(Series, 5, 7)) %>%
ggplot(aes(x = Date, y = value, group = Series, colour = Series)) +
geom_line() +
geom_vline(xintercept = 2019, color = "#A8ABD7", linetype= "dashed") +
theme_classic() +
theme(plot.title = element_text(size = 20),
plot.subtitle = element_text(size = 12),
axis.text.x = element_text(angle=90, hjust=1),
legend.text = element_text(size = 6),
legend.key.width=unit(0.2, "cm"),
legend.key.height = unit(0, "cm"),
legend.spacing.x = unit(0.1, "cm"),
legend.key.size = unit(0.01, "lines"),
legend.position = "bottom") +
scale_color_viridis_d() +
scale_x_continuous(breaks = seq(2005, 2025,by = 5)) +
guides(col = guide_legend(ncol = 15)) +
labs(title = "Motivo de la ausencia 2005-2019",
subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
y = "Rate",
x = "Year",
color = "Series") +
facet_wrap(.~ Group + Motivo)

Referencias
Athanasopoulos, G, Hyndman, RJ, Kourentzes, N, and Petropoulos, F
(2017). Forecasting with Temporal Hierarchies. European Journal of
Operational Research 262(1), 60–74.
Cochran, W.G. (1977), Sampling Techniques. Jonh Wiley and Sons, New
York.
Encuesta Nacional de Ocupación y Empleo (ENOE), población de 15 años
y más de edad. (2020). 50 preguntas y respuestas. Instituto Nacional de
Estadística Geografía e Informática. Retrieved May 7, 2020, from https://www.inegi.org.mx/programas/enoe/15ymas/default.html#Documentacion
Forecasting Hierarchical Time Series using R - Brillio Data Science -
Medium. (n.d.). Retrieved March 30, 2020, from https://medium.com/brillio-data-science/forecasting-hierarchical-time-series-using-r-598828dba435
R. J. Hyndman and A. Koehler (2006), Another look at measures of
forecast accuracy, International Journal of Forecasting, 22,
679-688.
Hyndman R.J., Ahmed R.A., Athanasopoulos G., Shang H.L., (2011),
Optimal combination forecasts for hierarchical time series,
Computational Statistics & Data Analysis 55(9), 2579 -2589.
Hyndman, R. J., Athanasopoulos, G., & Shang, H. L. (2014). hts:
An R Package for Forecasting Hierarchical or Grouped Time Series. https://cran.r-project.org/web/packages/hts/vignettes/hts.pdf?forcedefault=true
Hyndman, RJ (2017). forecast: Forecasting Functions for Time Series
and Linear Models. R package version 8.1. http://pkg.robjhyndman.com/forecast.
Librerías
Librerías que se usaron en el trabajo
[1] "purrr" "psych" "RColorBrewer" "tidyr" "tibble" "stringr"
[7] "htmlwidgets" "webshot" "ggpubr" "ggplot2" "knitr" "kableExtra"
[13] "dplyr" "openxlsx" "data.table" "hts" "forecast" "dygraphs"
[19] "extrafont" "showtext" "showtextdb" "sysfonts"
Nos ha servido a construir modelos de series de tiempo con datos
estructurales para fines de pronósticos.

This
work by [Diana Villasana Ocampo]{xmlns:cc= “http://creativecommons.org/ns#” property =
“cc:attributionName”} is licensed under a
Creative
Commons Attribution 4.0 International License.
LS0tDQp0aXRsZTogIkhpZXJhcmNoaWNhbCBUaW1lIFNlcmllcyINCnN1YnRpdGxlOiAiRW5jdWVzdGEgZGUgTmFjaW9uYWwgZGUgT2N1cGFjacOzbiB5IEVtcGxlbyAoRU5PRSkiDQphdXRob3I6ICJEaWFuYSBWaWxsYXNhbmEgT2NhbXBvIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIGNzczogInN0eWxlc3MuY3NzIg0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgICB0aGVtZTogZmxhdGx5DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiB0cnVlDQotLS0NCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gVFJVRSwgY2FjaGUubGF6eSA9IEZBTFNFLCBjb2xsYXBzZSA9IFRSVUUsIA0KICAgICAgICAgICAgICAgICAgICAgICNjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIiwNCiAgICAgICAgICAgICAgICAgICAgICBldmFsID0gVFJVRQ0KICAgICAgICAgICAgICAgICAgICAgICkNCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gcnByb2pyb290OjpmaW5kX3JzdHVkaW9fcm9vdF9maWxlKCkpDQpzZXR3ZChoZXJlOjpoZXJlKCkpDQpgYGANCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgcmVzdWx0cz1GQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiNGb250IFN0bHllDQpyZXF1aXJlKHNob3d0ZXh0KQ0KbGlicmFyeShleHRyYWZvbnQpDQp3aW5kb3dzRm9udHMoKQ0KYGBgDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIHJlc3VsdHM9RkFMU0UsIGV2YWwgPSBUUlVFfQ0KIyBMaWJyZXLDrWFzIGVuIGVsIGRvY3VtZW50bw0KcmVxdWlyZShkeWdyYXBocykNCnJlcXVpcmUoaHRzKQ0KcmVxdWlyZShkYXRhLnRhYmxlKQ0KcmVxdWlyZShvcGVueGxzeCkNCnJlcXVpcmUoZHBseXIpDQpyZXF1aXJlKGthYmxlRXh0cmEpDQpyZXF1aXJlKGtuaXRyKQ0KcmVxdWlyZShnZ3B1YnIpDQpyZXF1aXJlKGdncGxvdDIpDQpyZXF1aXJlKHdlYnNob3QpDQpyZXF1aXJlKGh0bWx3aWRnZXRzKQ0KcmVxdWlyZShzdHJpbmdyKQ0KcmVxdWlyZSh0aWJibGUpDQpyZXF1aXJlKHRpZHlyKQ0KcmVxdWlyZShSQ29sb3JCcmV3ZXIpDQpyZXF1aXJlKHBzeWNoKQ0KbGlicmFyeShwdXJycikNCmBgYA0KDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIHJlc3VsdHM9J2FzaXMnLCBldmFsPShvcHRzX2tuaXQkZ2V0KCdybWFya2Rvd24ucGFuZG9jLnRvJykgPT0gJ2xhdGV4Jyl9DQpjYXQoJ1xccGFnZWJyZWFrJykNCmBgYA0KDQoNCiMgSW50cm9kdWNjacOzbiAgIA0KDQpFbCBtw6l0b2RvIGRlIHNlcmllcyB0ZW1wb3JhbGVzIGplcsOhcnF1aWNhcyBlcyB1bmEgdMOpY25pY2EgYXZhbnphZGEgdXRpbGl6YWRhIHBhcmEgbW9kZWxhciB5IHByZWRlY2lyIGRhdG9zIHRlbXBvcmFsZXMgcXVlIGV4aGliZW4gdW5hIGVzdHJ1Y3R1cmEgamVyw6FycXVpY2EgbmF0dXJhbC4gIFN1IGFwbGljYWNpw7NuIGVmaWNheiBwdWVkZSBtZWpvcmFyIHNpZ25pZmljYXRpdmFtZW50ZSBsYSBwcmVjaXNpw7NuIGRlIGxvcyBwcm9uw7NzdGljb3MgeSBmYWNpbGl0YXIgbGEgdG9tYSBkZSBkZWNpc2lvbmVzIGVzdHJhdMOpZ2ljYXMgZW4gZGl2ZXJzYXMgw6FyZWFzIGRlIGFwbGljYWNpw7NuLCBlcyBlc3BlY2lhbG1lbnRlIMO6dGlsIGVuIHNpdHVhY2lvbmVzIGRvbmRlIGxvcyBkYXRvcyBzZSBwdWVkZW4gZGVzY29tcG9uZXIgZW4gbcO6bHRpcGxlcyBuaXZlbGVzIGRlIGFncmVnYWNpw7NuLCBjb21vIHBvciBlamVtcGxvLCBkZXNwbGF6YW1pZW50b3MgaW50ZXJub3MsIHJlZ2lvbmVzIHkgcGHDrXMuICAgDQoNCg0KKipDb21wb25lbnRlcyBQcmluY2lwYWxlcyoqICAgDQoNCjEuICoqRGVzY29tcG9zaWNpw7NuIEplcsOhcnF1aWNhKio6IERpdmlkZSBsb3MgZGF0b3MgZW4gbcO6bHRpcGxlcyBzZXJpZXMgdGVtcG9yYWxlcyBpbnRlcnJlbGFjaW9uYWRhcyBxdWUgc2Ugb3JnYW5pemFuIGVuIHVuYSBlc3RydWN0dXJhIGRlIMOhcmJvbCBqZXLDoXJxdWljby4gUG9yIGVqZW1wbG8sIGxvcyBkZXNwbGF6YW1pZW50b3MgaW50ZXJub3MgcHVlZGVuIGRlc2NvbXBvbmVyc2UgZW4gZGVzcGxhemFtaWVudG9zIGludGVybm9zIHBvciByZWdpw7NuLCB5IGEgc3UgdmV6LCBsb3MgZGVzcGxhemFtaWVudG9zIGludGVybm9zIHBvciByZWdpw7NuIHNlIGRlc2NvbXBvbmVuIHBvciBlc3RhZG9zLiAgICAgICANCg0KMi4gKipNb2RlbGFkbyBJbmRlcGVuZGllbnRlIHkgQ29uc2lzdGVudGUqKjogQ2FkYSBzZXJpZSB0ZW1wb3JhbCBkZW50cm8gZGUgbGEgamVyYXJxdcOtYSBzZSBtb2RlbGEgZGUgZm9ybWEgaW5kZXBlbmRpZW50ZSB1dGlsaXphbmRvIG3DqXRvZG9zIGRlIHNlcmllcyB0ZW1wb3JhbGVzIHRyYWRpY2lvbmFsZXMgY29tbyBBUklNQSBvIG3DqXRvZG9zIG3DoXMgYXZhbnphZG9zIGNvbW8gbW9kZWxvcyBkZSBlc3BhY2lvIGRlIGVzdGFkby4gICANCg0KMy4gKipDb25zaXN0ZW5jaWEgQWdyZWdhZGEqKjogTG9zIHByb27Ds3N0aWNvcyBkZSBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgaW5kaXZpZHVhbGVzIHNlIGFncmVnYW4gZGUgbWFuZXJhIGNvaGVyZW50ZSBwYXJhIGdlbmVyYXIgcHJvbsOzc3RpY29zIHByZWNpc29zIHkgY29uc2lzdGVudGVzIGVuIHRvZG9zIGxvcyBuaXZlbGVzIGRlIGxhIGplcmFycXXDrWEuICAgDQoNCioqQ29uc2lkZXJhY2lvbmVzIFByw6FjdGljYXMqKg0KDQotICoqU29mdHdhcmUgRXNwZWNpYWxpemFkbyoqOiBVdGlsaXphY2nDs24gZGUgaGVycmFtaWVudGFzIGNvbW8gYFJgIChjb24gcGFxdWV0ZXMgY29tbyBgaHRzYCkgbyBgUHl0aG9uYCBwYXJhIGltcGxlbWVudGFyIHkgYXV0b21hdGl6YXIgZWwgbcOpdG9kby4gICAgDQotICoqVmFsaWRhY2nDs24geSBBanVzdGUqKjogVmFsaWRhciBsb3MgbW9kZWxvcyBlbiBtw7psdGlwbGVzIG5pdmVsZXMgZGUgbGEgamVyYXJxdcOtYSB5IGFqdXN0YXIgc2Vnw7puIHNlYSBuZWNlc2FyaW8gcGFyYSBtZWpvcmFyIGxhIHByZWNpc2nDs24uICAgICANCg0KDQojIEVuY3Vlc3RhIE5hY2lvbmFsIGRlIE9jdXBhY2nDs24geSBFbXBsZW8gKGBFTk9FYCkgICAgICANCg0KTGEgRW5jdWVzdGEgTmFjaW9uYWwgZGUgT2N1cGFjacOzbiB5IEVtcGxlbyAoYEVOT0VgKSwgcmVhbGl6YWRhIHBvciBlbCBJbnN0aXR1dG8gTmFjaW9uYWwgZGUgRXN0YWTDrXN0aWNhIHkgR2VvZ3JhZsOtYSAoYElORUdJYCksIGVzIHVuYSBoZXJyYW1pZW50YSBlc2VuY2lhbCBwYXJhIG1lZGlyIGxhIGRpbsOhbWljYSBkZWwgbWVyY2FkbyBsYWJvcmFsIGVuIE3DqXhpY28uIFByb3BvcmNpb25hIGRhdG9zIGRldGFsbGFkb3Mgc29icmUgbGEgb2N1cGFjacOzbiwgZWwgZW1wbGVvLCBlbCBkZXNlbXBsZW8geSBvdHJhcyBjYXJhY3RlcsOtc3RpY2FzIHJlbGV2YW50ZXMgZGUgbGEgcG9ibGFjacOzbiBlY29uw7NtaWNhbWVudGUgYWN0aXZhLiAgDQoNCioqT2JqZXRpdm9zIFByaW5jaXBhbGVzKiogIA0KDQoxLiAqKk1lZGljacOzbiBkZSBsYSBQb2JsYWNpw7NuIEVjb27Ds21pY2FtZW50ZSBBY3RpdmEgKFBFQSkqKjogSWRlbnRpZmljYXIgbGEgcHJvcG9yY2nDs24gZGUgbGEgcG9ibGFjacOzbiBxdWUgcGFydGljaXBhIGVuIGVsIG1lcmNhZG8gbGFib3JhbCwgaW5jbHV5ZW5kbyB0YW50byBhIGxhcyBwZXJzb25hcyBvY3VwYWRhcyBjb21vIGEgbGFzIGRlc29jdXBhZGFzLiAgDQoNCjIuICoqQW7DoWxpc2lzIGRlbCBFbXBsZW8qKjogUHJvcG9yY2lvbmFyIGluZm9ybWFjacOzbiBzb2JyZSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZWwgZW1wbGVvLCBpbmNsdXllbmRvIGxhIG5hdHVyYWxlemEgZGVsIHRyYWJham8sIGxhcyBjb25kaWNpb25lcyBsYWJvcmFsZXMsIGxvcyBzZWN0b3JlcyBlY29uw7NtaWNvcyB5IGxhcyB0YXNhcyBkZSBlbXBsZW8gZm9ybWFsIGUgaW5mb3JtYWwuICAgDQoNCjMuICoqRXZhbHVhY2nDs24gZGVsIERlc2VtcGxlbyoqOiBFc3RpbWFyIGxhIHRhc2EgZGUgZGVzZW1wbGVvIHkgYW5hbGl6YXIgbGFzIGNhcmFjdGVyw61zdGljYXMgZGUgbGEgcG9ibGFjacOzbiBkZXNvY3VwYWRhLCBpbmNsdXllbmRvIGxhIGR1cmFjacOzbiBkZWwgZGVzZW1wbGVvIHkgbG9zIGVzZnVlcnpvcyBkZSBiw7pzcXVlZGEgZGUgZW1wbGVvLiAgIA0KDQo0LiAqKkluZm9ybWFjacOzbiBTb2Npb2Vjb27Ds21pY2EqKjogUmVjb3BpbGFyIGRhdG9zIHNvYnJlIGxhIGVkdWNhY2nDs24sIGxvcyBpbmdyZXNvcyB5IG90cmFzIHZhcmlhYmxlcyBzb2Npb2Vjb27Ds21pY2FzIHF1ZSBhZmVjdGFuIHkgc29uIGFmZWN0YWRhcyBwb3IgZWwgZW1wbGVvIHkgZWwgZGVzZW1wbGVvLiAgDQogDQoqKkNvbXBvbmVudGVzIFByaW5jaXBhbGVzKiogICAgDQoNCi0gKipFbmN1ZXN0YXMgVHJpbWVzdHJhbGVzKio6IExhIEVOT0Ugc2UgcmVhbGl6YSBkZSBtYW5lcmEgY29udGludWEsIGNvbiByZXN1bHRhZG9zIHB1YmxpY2Fkb3MgdHJpbWVzdHJhbG1lbnRlLCBsbyBxdWUgcGVybWl0ZSB1biBzZWd1aW1pZW50byBjZXJjYW5vIGRlIGxhcyB0ZW5kZW5jaWFzIGxhYm9yYWxlcy4gICANCi0gKipDb2JlcnR1cmEgTmFjaW9uYWwqKjogTGEgZW5jdWVzdGEgYWJhcmNhIHRvZGFzIGxhcyBlbnRpZGFkZXMgZmVkZXJhdGl2YXMgZGUgTcOpeGljbywgb2ZyZWNpZW5kbyB1bmEgdmlzacOzbiBjb21wcmVuc2l2YSB5IGRldGFsbGFkYSBkZWwgbWVyY2FkbyBsYWJvcmFsIGEgbml2ZWwgbmFjaW9uYWwgeSByZWdpb25hbC4gICAgDQotICoqQW1wbGl0dWQgZGUgVGVtYXMqKjogSW5jbHV5ZSBpbmZvcm1hY2nDs24gc29icmUgZW1wbGVvIGZvcm1hbCBlIGluZm9ybWFsLCBzdWJlbXBsZW8sIG9jdXBhY2lvbmVzLCBpbmdyZXNvcywgY29uZGljaW9uZXMgZGUgdHJhYmFqbyB5IG3DoXMuICAgIA0KDQoqKkFwbGljYWNpb25lcyoqICAgIA0KDQotIGBQb2zDrXRpY2FzIFDDumJsaWNhc2A6IExvcyBkYXRvcyBkZSBsYSBFTk9FIHNvbiBjcnVjaWFsZXMgcGFyYSBsYSBmb3JtdWxhY2nDs24geSBldmFsdWFjacOzbiBkZSBwb2zDrXRpY2FzIGxhYm9yYWxlcywgZWR1Y2F0aXZhcyB5IGVjb27Ds21pY2FzLiAgIA0KLSBgSW52ZXN0aWdhY2nDs24gQWNhZMOpbWljYWA6IFByb3BvcmNpb25hIHVuYSBiYXNlIGRlIGRhdG9zIHJpY2EgcGFyYSBlc3R1ZGlvcyBzb2JyZSBlbCBtZXJjYWRvIGxhYm9yYWwsIGxhIGVjb25vbcOtYSBkZWwgdHJhYmFqbyB5IGxhIHNvY2lvbG9nw61hIGRlbCBlbXBsZW8uICAgDQotIGBBbsOhbGlzaXMgU2VjdG9yaWFsYDogQXl1ZGEgYSBpZGVudGlmaWNhciB0ZW5kZW5jaWFzIHkgZGVzYWbDrW9zIGVzcGVjw61maWNvcyBlbiBkaXN0aW50b3Mgc2VjdG9yZXMgZWNvbsOzbWljb3MsIGluZm9ybWFuZG8gZGVjaXNpb25lcyBlbXByZXNhcmlhbGVzIHkgZ3ViZXJuYW1lbnRhbGVzLiAgIA0KDQoqKkNvbnNpZGVyYWNpb25lcyBQcsOhY3RpY2FzKiogICAgDQoNCi0gKipBY2Nlc28gYSBEYXRvcyoqOiBMb3MgZGF0b3MgZGUgbGEgRU5PRSBlc3TDoW4gZGlzcG9uaWJsZXMgcMO6YmxpY2FtZW50ZSBhIHRyYXbDqXMgZGVsIElORUdJLCBmYWNpbGl0YW5kbyBzdSB1c28gcGFyYSBhbsOhbGlzaXMgeSBlc3R1ZGlvcyBkZXRhbGxhZG9zLg0KLSAqKk1ldG9kb2xvZ8OtYSBSaWd1cm9zYSoqOiBMYSBlbmN1ZXN0YSBzaWd1ZSBlc3TDoW5kYXJlcyBtZXRvZG9sw7NnaWNvcyBlc3RyaWN0b3MsIGFzZWd1cmFuZG8gbGEgY2FsaWRhZCB5IGNvbmZpYWJpbGlkYWQgZGUgbG9zIGRhdG9zLg0KLSAqKkFjdHVhbGl6YWNpw7NuIENvbnRpbnVhKio6IExhIEVOT0Ugc2UgYWN0dWFsaXphIGNvbnRpbnVhbWVudGUsIHBlcm1pdGllbmRvIHVuIG1vbml0b3JlbyBwcmVjaXNvIGRlIGxhcyBkaW7DoW1pY2FzIGxhYm9yYWxlcyBhIGxvIGxhcmdvIGRlbCB0aWVtcG8uICAgIA0KDQojIyBEaXNlw7FvIGNvbmNlcHR1YWwgDQoNCkxhIHBvYmxhY2nDs24gb2JqZXRpdm8gZGUgbGEgZW5jdWVzdGEgZXN0w6EgY29uZm9ybWFkYSBwb3IgdG9kb3MgbG9zIHF1ZSByZXNpZGVuIGhhYml0dWFsbWVudGUgbGFzIHZpdmllbmRhcyBzZWxlY2Npb25hZGFzLiBMb3MgaW5zdHJ1bWVudG9zIGRlIGNhcHRhY2nDs24gbcOhcyBpbXBvcnRhbnRlcyBzb24gZWwgYEN1ZXN0aW9uYXJpbyBTb2Npb2RlbW9ncsOhZmljbyAoQ1MpYCB5IGVsIGBDdWVzdGlvbmFyaW8gZGUgT2N1cGFjacOzbiB5IEVtcGxlbyAoQ09FKWAuIExhIGluZm9ybWFjacOzbiByZWZlcmVudGUgYSBsb3MgaG9nYXJlcyB5IGEgbGFzIGNhcmFjdGVyw61zdGljYXMgc29jaW9kZW1vZ3LDoWZpY2FzIGRlIGxvcyByZXNpZGVudGVzIGRlIGxhIHZpdmllbmRhIHNlIHJlZ2lzdHJhIGVuIGVsIGBDU2AsIG1pZW50cmFzIHF1ZSBlbCBgQ09FYCBjb250aWVuZSB2YXJpYWJsZXMgcXVlIGlkZW50aWZpY2FuIGVuIHByaW1lciBsdWdhciBsYSBjb25kaWNpw7NuIGRlIGFjdGl2aWRhZCB5IGVuIHNlZ3VuZG8gdMOpcm1pbm8gcHJlZ3VudGFzIGVzcGVjw61maWNhcyBwYXJhIGNhZGEgdW5vIGRlIGxvcyB1bml2ZXJzb3MuIEVzIG5lY2VzYXJpbyBtZW5jaW9uYXIgcXVlIGVsIGBDT0VgIHNlIGxldmFudGEgYSBsYSBwb2JsYWNpw7NuIGRlIDEyIGHDsW9zIGVuIGFkZWxhbnRlLCBzaW4gZW1iYXJnbywgcG9yIGN1ZXN0aW9uZXMgbWV0b2RvbMOzZ2ljYXMgZGVsIG1hcmNvIGRlIGxhIE9DREUgc2UgcMO6YmxpY2EgcGFyYSBsYSBwb2JsYWNpw7NuIGRlIDE1IGHDsW9zIGVuIGFkZWxhbnRlLiAgICAgICAgDQoNCiMjIERpc2XDsW8gdGVtcG9yYWwgDQoNCkxhIGBFTk9FYCBlcyB1bmEgZW5jdWVzdGEgcGFuZWwgZGUgcm90YXRvcmlvLCBlcyBkZWNpciwgdGllbmUgdW5hIG11ZXN0cmEgZGUgdml2aWVuZGFzIGRpdmlkaWRhIGVuIDUgcGFuZWxlcyBkZSByb3RhY2nDs24uIERlIGxvcyBjdWFsZXMsIHJvdGEgdW5vIGNhZGEgdHJpbWVzdHJlOyBjb25zZXJ2YW5kbyBkZSBlc3RhIG1hbmVyYSwgZWwgODAgcG9yIGNpZW50byBkZSBsYSBtdWVzdHJhIGVudHJlIGRvcyB0cmltZXN0cmVzIGNvbnNlY3V0aXZvcy4gIExvIHF1ZSBwZXJtaXRlIGxsZXZhciBhIGNhYm8gZG9zIGltcG9ydGFudGVzIGFjdGl2aWRhZGVzOiBzdXN0aXR1aXIgZWwgbWFyY28gbXVlc3RyYWwgeSBjYW1iaWFyIGVzcXVlbWEgZGUgbXVlc3RyZW8uICAgICANCg0KUG9yIG90cmEgcGFydGUsIHRvZGEgbGEgY2FudGlkYWQgZGUgaW5mb3JtYWNpw7NuIHJlY2FiYWRhIGRlIGxhIG1pc21hIHVuaWRhZCBkZSBtdWVzdHJlbyBlbiBkb3MgbyBtw6FzIHBlcmlvZG9zIGNvbnNlY3V0aXZvcyBwZXJtaXRpcsOhIHRlw7NyaWNhbWVudGUgaW5jcmVtZW50YXIgbGEgcHJlY2lzacOzbiBkZSBsYXMgZXN0aW1hY2lvbmVzLCBwcmluY2lwYWxtZW50ZSBkZWwgY2FtYmlvIGVuIGVsbGFzLiAgQ29jaHJhbiAoMTk3NykgY29pbmNpZGUgY29uIGVzdG8geSBhZGVtw6FzIGVzdGFibGVjZSBxdWUsIGVuIGxhIG9idGVuY2nDs24gZGUgbGFzIGVzdGltYWNpb25lcyBhY3R1YWxlcywgc2UgZ2FuYSBsYSBtaXNtYSBwcmVjaXNpw7NuIHNpIHNlIGNvbnNlcnZhIGxhIG11ZXN0cmEgaW5pY2lhbCBvIHNlIGNhbWJpYSBlbiBjYWRhIG9jYXNpw7NuLiAgICANCg0KIyMgQ29uZGljacOzbiBkZSBSZXNpZGVuY2lhDQoNClVuIGFzcGVjdG8gcmVsZXZhbnRlIHBvciBjb25zaWRlcmFyIGZ1ZSBpZGVudGlmaWNhciBsYSBjb25kaWNpw7NuIGRlIHJlc2lkZW5jaWEsIGEgcXVpZW5lcyBkZSBsb3MgcmVzaWRlbnRlcyBjb250aW51YWJhbiB2aXZpZW5kbyBlbiBlbCBob2dhciBvIGVuIG90cm9zIHTDqXJtaW5vcyBhIHF1aWVuZXMgbm8gaGFuIGVzdGFkbyBlbiB1biBwcm9jZXNvIGRlIHRyYW5zaWNpw7NuIGRlIHJlc2lkZW5jaWEsIGFzw60gY29tbyBsb3MgYXVzZW50ZXMgZGVmaW5pdGl2b3MgeSBhIGxvcyBudWV2b3MgcmVzaWRlbnRlcy4gQWwgcmVzcGVjdG8sIGNhYmUgYWNvdGFyLCBxdWUgZWwgZGlzZcOxbyBjb25jZXB0dWFsIGRlbCBDdWVzdGlvbmFyaW8gU29jaW9kZW1vZ3LDoWZpY28gaWRlbnRpZmljYSBhIHF1aWVuZXMgeWEgbm8gc2UgZW5jdWVudHJhbiBwb3IgaGFiZXIgcGFydGlkbyBhIG90cm8gbHVnYXIgcG9yIGRpdmVyc2FzIGNhdXNhcyBlbnRyZSDDqXN0YXMgcG9yIG1vcnRhbGlkYWQgKGBBdXNlbnRlcyBEZWZpbml0aXZvc2ApIHkgZGlzdGluZ3VlIHF1aWVuZXMgc29uIG51ZXZvcyBlbiBsbyBkZWwgbWlzbW8gaG9nYXIgcG9yIGhhYmVyIGFycmliYWRvIGRlIGFsZ8O6biBsdWdhciBvdHJvIGx1Z2FyIHBvciBkaXZlcnNhcyBjYXVzYXMgZW50cmUgZWxsYXMgZWwgbmFjaW1pZW50byAoYE51ZXZvIFJlc2lkZW50ZXNgKS4gICAgICAgDQoNCg0KIyMgTW90aXZvIGRlIGxhIG1pZ3JhY2nDs24gW14xXSAgIA0KDQpbXjFdOihodHRwczovL3d3dy5pbmVnaS5vcmcubXgvcHJvZ3JhbWFzL2Vub2UvMTV5bWFzLykgIA0KDQpMb3MgZGF0b3Mgc29uIHJlY29waWxhZG9zIGRlIGxhIGBFTk9FYCwgc2llbmRvLCBsYSBmdWVudGUgcHJpbmNpcGFsIGRlIGluZm9ybWFjacOzbiBzb2JyZSBlbCBtZXJjYWRvIGxhYm9yYWwgbWV4aWNhbm8gYWwgb2ZyZWNlciBkYXRvcyBkZSBtYW5lcmEgdHJpbWVzdHJhbCBkZSBsYSBmdWVyemEgZGUgdHJhYmFqbywgb2N1cGFjacOzbiwgbGEgaW5mb3JtYWxpZGFkIGxhYm9yYWwsIGxhIHN1Ym9jdXBhY2nDs24geSBkZXNvY3VwYWNpw7NuLiAgIA0KDQpMYSBFTk9FIGluaWNpYSBzdSBsZXZhbnRhbWllbnRvIGVuIDIwMDUgeSBzZSByZXBpdGUgZW4gaW50ZXJ2YWxvcyByZWd1bGFyZXMgZGUgdGllbXBvLCBjYXB0YW5kbyBsYSBpbmZvcm1hY2nDs24gYSBuaXZlbCBuYWNpb25hbC4gRXN0ZSB0aXBvIGRlIGVuY3Vlc3RhIHBlcm1pdGUgY2FwdGFyIHkgY29ub2NlciBkZSBtZWpvciBtYW5lcmEgbGFzIGNhcmFjdGVyw61zdGljYXMgc29jaW9lY29uw7NtaWNhcyBkZSBsYSBwb2JsYWNpw7NuIG1leGljYW5hIGRlIDE1IGHDsW9zIHkgbcOhcy4gICANCg0KRWwgb2JqZXRpdm8gZGVsIHRyYWJham8gZXMgaW1wbGVtZW50YXIgeSBjb21wYXJhciBsYXMgIGRpZmVyZW50ZXMgc2VyaWVzIGRlIHRpZW1wbyBkZSBtYW5lcmEgamVyw6FycXVpY2EgeSBwZXJtaXRpciBlbCBkZXNnbG9zZSBkZSBsYXMgY2F1c2FzIGRlIG1pZ3JhY2nDs24uICAgICAgDQoNCiMjIEluZGljYWRvcmVzIA0KDQpUb21hbmRvIGxhcyBwcmVndW50YXMgZGVsIGN1ZXN0aW9uYXJpbyBkZSBsYXMgY3VhbGVzIHNvbiBtw6FzIGRlICp0cmVzY2llbnRhcyBiYXNlcyBkZSBkYXRvcyogY29uICoxNTAgbWlsIGNhc29zKiBhIG5pdmVsIG5hY2lvbmFsIGVuIGxvcyBkaWZlcmVudGVzIHBlcmlvZG9zIGRlIHRpZW1wby4gICAgICANCg0KTGFzIGNvYmVydHVyYXMgZ2VvZ3LDoWZpY2FzIG8gZG9taW5pb3MgZGUgZXN0dWRpbyBwYXJhIGxhcyBjdWFsZXMgc2UgZ2VuZXJhbiBlc3RpbWFjaW9uZXMgc29uOiAgICANCg0KLQlgQ2l1ZGFkIEF1dG9yZXByZXNlbnRhZGFgICAgDQotCWBFbnRpZGFkIEZlZGVyYXRpdmFgICAgDQotCWBOYWNpb25hbGAgICANCg0KU2UgdG9tYSBjb21vIHJlZmVyZW5jaWEgbGEgcHJlZ3VudGEgYGNzX2FkX21vdGAgKipNb3Rpdm8gZGUgbGEgbWlncmFjacOzbiAqKiwgZW4gbGEgY3VhbCBzZSBkZXNnbG9zYSBlbiBsYXMgc2lndWllbnRlcyBjYXRlZ29yw61hcy4gICANCg0KLSBUcmFiYWpvICAgICANCi0gRXN0dWRpbyAgIA0KLSBTZSBjYXPDsyBvIHVuacOzICAgICANCi0gU2Ugc2VwYXLDsyBvIGRpdm9yY2nDsyAgICANCi0gUHJvYmxlbWFzIGRlIHNhbHVkICAgDQotIFJldW5pcnNlIGNvbiBsYSBmYW1pbGlhICAgICAgICAgICANCi0gSW5zZWd1cmlkYWQgcMO6YmxpY2EgICAgICANCi0gRmFsbGVjacOzICAgICAgIA0KLSBPdHJvIE1vdGl2byAgICAgICANCi0gTm8gc2FiZSAgDQoNCkRlIGxhcyBjdWFsZXMgc29sbyBzZSB0b21hbiA1IGNhc29zIHBhcmEgZWwgcHJvcMOzc2l0byBkZWwgcHJlc2VudGUgdHJhYmFqby4gICANCg0KKipCYXNlIGRlIGRhdG9zKiogICANCg0KU2UgY2FyZ2FuIGxhcyBiYXNlcyBkZSBkYXRvcyBxdWUgY29udGllbmVuIGxvcyBjaW5jbyBwcmluY2lwYWxlcyBtb3Rpdm9zIGRlIGxhIG1pZ3JhY2nDs24sIHRvbWFuZG8gY29tbyByZWZlcmVuY2lhIGxvcyBkYXRvcyBkZWwgMjAwNSBhbCAyMDE5LiAgIA0KDQotIGAoZGV0ZWN0RGF0ZXMgPSBUUlVFKWA7IGxhcyBmZWNoYXMgc2UgZGV0ZWN0YW4geSBzZSBjb252aWVydGVuIGF1dG9tw6F0aWNhbWVudGUgZW4gb2JqZXRvcyBkZSBmZWNoYSBlbiBSLiAgDQoNCmBgYHtyfQ0KVC5UcmFiYWpvIDwtIHJlYWQueGxzeChwYXN0ZTAoaGVyZTo6aGVyZSgpLCAiL0Jhc2UgZGUgZGF0b3MvUmVzdWx0YWRvcyBFTk9FLnhsc3giKSwNCiAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQgPSAiVHJhYmFqbyIsIA0KICAgICAgICAgICAgICAgICAgICAgICBjb2xOYW1lcyA9IFRSVUUsIGRldGVjdERhdGVzID0gVFJVRSkNClQuRXN0dWRpbyA8LSByZWFkLnhsc3gocGFzdGUwKGhlcmU6OmhlcmUoKSwgIi9CYXNlIGRlIGRhdG9zL1Jlc3VsdGFkb3MgRU5PRS54bHN4IiksIA0KICAgICAgICAgICAgICAgICAgICAgICBzaGVldCA9ICJFc3R1ZGlvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgY29sTmFtZXMgPSBUUlVFLCANCiAgICAgICAgICAgICAgICAgICAgICAgZGV0ZWN0RGF0ZXMgPSBUUlVFKQ0KVC5VbmlvbiA8LSByZWFkLnhsc3gocGFzdGUwKGhlcmU6OmhlcmUoKSwgIi9CYXNlIGRlIGRhdG9zL1Jlc3VsdGFkb3MgRU5PRS54bHN4IiksDQogICAgICAgICAgICAgICAgICAgICBzaGVldCA9ICJVbmlvbiIsDQogICAgICAgICAgICAgICAgICAgICBjb2xOYW1lcyA9IFRSVUUsIA0KICAgICAgICAgICAgICAgICAgICAgZGV0ZWN0RGF0ZXMgPSBUUlVFKQ0KVC5EaXZvcmNpbyA8LSByZWFkLnhsc3gocGFzdGUwKGhlcmU6OmhlcmUoKSwgIi9CYXNlIGRlIGRhdG9zL1Jlc3VsdGFkb3MgRU5PRS54bHN4IiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQgPSAiRGl2b3JjaW8iLCANCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbE5hbWVzID0gVFJVRSwgDQogICAgICAgICAgICAgICAgICAgICAgICBkZXRlY3REYXRlcyA9IFRSVUUpDQpULkZhbWlsaWEgPC0gcmVhZC54bHN4KHBhc3RlMChoZXJlOjpoZXJlKCksICIvQmFzZSBkZSBkYXRvcy9SZXN1bHRhZG9zIEVOT0UueGxzeCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQgPSAiUmV1bmlyc2UgY29uIHVuIGZhbWlsaWFyIiwgDQogICAgICAgICAgICAgICAgICAgICAgIGNvbE5hbWVzID0gVFJVRSwgDQogICAgICAgICAgICAgICAgICAgICAgIGRldGVjdERhdGVzID0gVFJVRSkNCmBgYA0KDQoNClNlIGRpdmlkZSBlbnRyZSBsYSBwb2JsYWNpw7NuLCBkZWJpZG8gYSBxdWUgc2kgdG9tYW4gbG9zIGFic29sdXRvcyBkZSBsYXMgcGVyc29uYXMgcXVlIGNhbWJpYXJvbiBkZSByZXNpZGVuY2lhIHBvciBhbGd1bm8gZGUgbG9zIGRpZmVyZW50ZXMgbW90aXZvcyBkZSBhdXNlbmNpYS4gIEVzdG9zIHRpZW5kZW4gYSBzZXIgbWF5b3JlcyBlbiBhbGd1bmFzIGNpdWRhZGVzLCBkZWJpZG8gc2UgdGllbmUgbWF5b3IgZGVuc2lkYWQgZGUgcG9ibGFjacOzbi4gIFBlcm1pdGllbmRvIGFzw60gbGEgY29tcGFyYWJpbGlkYWQgZW50cmUgY2l1ZGFkZXMgcG9yIHVuYSByYXrDs24gZGUgY2FkYSAxMDAwIHBlcnNvbmFzLiAgIA0KDQpTZSBkZWZpbmUgbGEgZnVuY2nDs24gbGxhbWFkYSBgZGl2aWRlX2NvbHVtbnNgIHF1ZSB0b21hIGRvcyBkYXRhLmZyYW1lcyAoYGRmMWAgeSBgZGYyYCkuIExhIGZ1bmNpw7NuOiAgIA0KDQotIEV4dHJhZSB0b2RhcyBsYXMgY29sdW1uYXMgZGUgZGYxIHkgZGYyIGRlc2RlIGxhIHNlZ3VuZGEgY29sdW1uYSBlbiBhZGVsYW50ZS4gICANCi0gVXNhIGxhIGZ1bmNpw7NuIGBtYXAyX2RmY2AgZGVsIHBhcXVldGUgYHB1cnJyYCBwYXJhIGRpdmlkaXIgY2FkYSBwYXIgZGUgY29sdW1uYXMgY29ycmVzcG9uZGllbnRlcyBkZSBkZjEgeSBkZjIsIG11bHRpcGxpY2FuZG8gZWwgcmVzdWx0YWRvIHBvciAxMDAwLiAgICAgDQotIFNlIHJlY29uc3RydXllIGVsIGRhdGEuZnJhbWUgcmVzdWx0YW50ZSBjb21iaW5hbmRvIGxhIHByaW1lcmEgY29sdW1uYSBkZSBkZjEgY29uIGxhcyBjb2x1bW5hcyByZXN1bHRhbnRlcyBkZSBsYSBkaXZpc2nDs24uICAgDQoNCmBgYHtyfQ0KI1BvYmxhY2nDs24gVG90YWwgIA0KVC5Qb2JsYWNpb24gPC0gcmVhZC54bHN4KHBhc3RlMChoZXJlOjpoZXJlKCksICIvQmFzZSBkZSBkYXRvcy9SZXN1bHRhZG9zIEVOT0UueGxzeCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICBzaGVldCA9ICJQb2JsYWNpw7NuIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgY29sTmFtZXMgPSBUUlVFLCANCiAgICAgICAgICAgICAgICAgICAgICAgICBkZXRlY3REYXRlcyA9IFRSVUUpDQojIFZlY3RvciBkZSB0aWVtcG8NClBlcmlvZG8gPC0gVC5Qb2JsYWNpb24kUGVyaW9kbyAjU2UgZ3VhcmRhIGVsIHZlY3RvciB0aWVtcG8NCg0KI0NyZWFtb3MgdW5hIGZ1bmNpw7NuIHBlcnNvbmFsaXphZGEgcGFyYSBkaXZpZGlyIGxvcyBlbGVtZW50b3MgZGVzZGUgbGEgc2VndW5kYSBjb2x1bW5hIGVuIGFkZWxhbnRlDQpkaXZpZGVfY29sdW1ucyA8LSBmdW5jdGlvbihkZjEsIGRmMikgew0KICAgICAgICAgICAgICAgICAgICBkZjFfY29scyA8LSBkZjFbLCAyOm5jb2woZGYxKV0NCiAgICAgICAgICAgICAgICAgICAgZGYyX2NvbHMgPC0gZGYyWywgMjpuY29sKGRmMildDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAjIEFwbGljYW1vcyBsYSBkaXZpc2nDs24gdXNhbmRvIG1hcDINCiAgICAgICAgICAgICAgICAgICAgcmVzdWx0X2NvbHMgPC0gbWFwMl9kZmMoZGYxX2NvbHMsIGRmMl9jb2xzLCB+IC54IC8gLnkgKiAxMDAwKQ0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgIyBSZWNvbnN0cnVpbW9zIGVsIGRhdGEuZnJhbWUgY29uIGxhIHByaW1lcmEgY29sdW1uYSBkZSBkZjEgeSBsYXMgY29sdW1uYXMgcmVzdWx0YW50ZXMNCiAgICAgICAgICAgICAgICAgICAgcmVzdWx0IDwtIGJpbmRfY29scyhkZjFbLCAxLCBkcm9wID0gRkFMU0VdLCByZXN1bHRfY29scykNCiAgICAgICAgICAgICAgICAgICAgcmVzdWx0DQp9DQoNCnRhYmxhcyA8LSBscyhwYXR0ZXJuID0gIlQuIikNCmZvcihpIGluIDE6Nil7DQogIGFzc2lnbihwYXN0ZTAodGFibGFzW2ldKSwgZGl2aWRlX2NvbHVtbnMoZ2V0KHBhc3RlMCh0YWJsYXNbaV0pKSwgVC5Qb2JsYWNpb24pKQ0KfQ0KYGBgDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCiMgVG9kbyBlbiB1biBkYXRhLmZyYW1lDQpteWRhdGEgPC0gZG8uY2FsbChjYmluZC5kYXRhLmZyYW1lLCBsaXN0KFQuVHJhYmFqbywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVC5Fc3R1ZGlvICU+JSBzZWxlY3QoLWMoIlBlcmlvZG8iKSkgLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBULlVuaW9uICU+JSBzZWxlY3QoLWMoIlBlcmlvZG8iKSkgLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBULkRpdm9yY2lvICU+JSBzZWxlY3QoLWMoIlBlcmlvZG8iKSkgLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBULkZhbWlsaWEgJT4lIHNlbGVjdCgtYygiUGVyaW9kbyIpKSkpDQpgYGANCg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnRhYmxhIDwtIGhlYWQobXlkYXRhWzE6Nl0pDQprbml0cjo6a2FibGUodGFibGEsDQogICAgICAgICAgICAgZGlnaXRzID0gMiwNCiAgICAgICAgICAgICBhbGlnbiA9ICJjIiwgDQogICAgICAgICAgICAgY2FwdGlvbiA9ICJUYXNhcyBkZSBtaWdyYWNpw7NuIHBvciBhbGfDum4gbW90aXZvIGRlIGF1c2VuY2lhIikgJT4lDQprYWJsZV9zdHlsaW5nKHBvc2l0aW9uID0gImNlbnRlciIsICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygiY29uZGVuc2VkIiwgInJlc3BvbnNpdmUiLCAiYm9yZGVyZWQiLCAiaG92ZXIiKSwNCiAgICAgICAgICAgICAgICBmb250X3NpemUgPSAxMCkgJT4lDQprYWJsZV9jbGFzc2ljKGZ1bGxfd2lkdGggPSBGQUxTRSwgaHRtbF9mb250ID0gIkNlbnR1cnkgR290aGljIikNCmBgYA0KDQpBIGNvbnRpbnVhY2nDs24gc2UgZXN0cnVjdHVyYSBsYSBqZXJhcnF1w61hIGRlIGxvcyBuaXZlbGVzIGRlIGFjdWVyZG8gYWwgdGlwbyBkZSBkZXNhZ3JlZ2FjacOzbiBnZW9ncsOhZmljYSwgZW4gbGEgY3VhbCBzZSBhZ3J1cGFuIGxhcyAzMiBjaXVkYWRlcyBhdXRvcmVwcmVzZW50YWRhcyBlbiByZWdpb25lcy4gICAgDQotIFNlIGNvbnNpZGVyYXJvbiA1IHJlZ2lvbmVzIGRlbCBwYcOtcyBwYXJhIHF1ZSBsb3MgY8OhbGN1bG9zIG5vIGZ1ZXJhbiB0YW4gZXh0ZW5zb3MgYSBsYSBob3JhIGRlIGludGVycHJldGFybG9zLiAgIA0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KdGFibGEgPC0gZGF0YS5mcmFtZShSZWdpb25lcyA9IGMocmVwKCJDZW50cm8iLCA3KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiTm9yZXN0ZSIsIDUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJOb3JvZXN0ZSIsIDUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJPY2NpZGVudGUiLCA4KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIlN1cmVzdGUiLCA3KSksDQogICAgICAgICAgICAgICAgICAgIENWRV9DaXVkYWQgPSBjKCIxMSIsIAkiMjQiLCAJIjAxIiwgCSIzMiIsIAkiMDQiLCAJIjE0IiwgCSIyOSIsIAkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIxIiwgCSIwMyIsIAkiMDYiLCAJIjE1IiwgCSIwOSIsIAkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjA4IiwgCSIxOSIsIAkiMjAiLCAJIjMwIiwgCSIxOCIsIAkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjEyIiwgCSIyNyIsIAkiMDIiLCAJIjA1IiwgCSIxMyIsIAkiMjgiLCAJIjIyIiwgCSIyNiIsIAkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjMxIiwgCSIyMyIsIAkiMDciLCAJIjI1IiwgCSIxNyIsIAkiMTAiLCAJIjE2IiksDQogICAgICAgICAgICAgICAgICAgIENpdWRhZCA9IGMoIkFjYXB1bGNvIiwgCSJDdWVybmF2YWNhIiwgCSJNw6l4aWNvIiwgCSJQYWNodWNhIiwgCSJQdWVibGEiLCAJIlRvbHVjYSIsIAkiVGxheGNhbGEiLCAJDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkR1cmFuZ28iLCAJIk1vbnRlcnJleSIsIAkiU2FuIEx1aXMgUG90b3PDrSIsIAkiU2FsdGlsbG8iLCAJIlRhbXBpY28iLCAJDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNoaWh1YWh1YSIsIAkiQ3VsaWFjw6FuIiwgCSJIZXJtb3NpbGxvIiwgCSJMYSBQYXoiLCAJIlRpanVhbmEiLCAJDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFndWFzY2FsaWVudGVzIiwgCSJDb2xpbWEiLCAJIkd1YWRhbGFqYXJhIiwgCSJMZcOzbiIsIAkiTW9yZWxpYSIsIAkiUXVlcsOpdGFybyIsIAkiVGVwaWMiLCAJIlphY2F0ZWNhcyIsIAkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2FuY8O6biIsIAkiQ2FtcGVjaGUiLCAJIk3DqXJpZGEiLCAJIk9heGFjYSIsIAkiVHV4dGxhIEd1dXRpw6lycmV6IiwgCSJWZXJhY3J1eiIsIAkiVmlsbGFoZXJtb3NhIikpDQoNCnRhYmxhJT4lDQprYWJsZShhbGlnbiA9ICJjIiwNCiAgICAgIGNvbC5uYW1lcyA9IGMoIlJlZ2nDs24iLCAiQ2xhdmUiLCAiQ2l1ZGFkIiksDQogICAgICBjYXB0aW9uPSAiRXN0cnVjdHVyYSBnZW5lcmFsIGRlIGxhcyByZWdpb25lcyIpICU+JQ0KIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJjb25kZW5zZWQiLCAicmVzcG9uc2l2ZSIsICJib3JkZXJlZCIsICJob3ZlciIpLA0KICAgICAgICAgICAgICAgZm9udF9zaXplID0gNywNCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImNlbnRlciIsDQogICAgICAgICAgICAgICBsYXRleF9vcHRpb25zPSAiSE9MRF9wb3NpdGlvbiIpICU+JSANCiAgZ3N1YigiZm9udC1zaXplOiBpbml0aWFsICFpbXBvcnRhbnQ7IiwgImZvbnQtc2l6ZTogMTBwdCAhaW1wb3J0YW50OyIsIC4pICU+JQ0KICAgZ3N1YigidGV4dC1hbGlnbjogaW5pdGlhbCAhaW1wb3J0YW50OyIsICJ0ZXh0LWFsaWduOiBqdXN0aWZ5ICFpbXBvcnRhbnQ7IiwgLikNCmBgYA0KDQojIyBFc3RydWN0dXJhIGplcsOhcnF1aWNhICANCg0KQ2FkYSB1bm8gZGUgZXN0b3MgZ3J1cG9zIHNlIGRlc2dsb3NhbiBlbiBjYXRlZ29yw61hcyBxdWUgZXN0w6FuIGFuaWRhZGFzIGRlbnRybyBkZSBsYXMgY2F0ZWdvcsOtYXMgZGUgZ3J1cG9zIG3DoXMgZ3JhbmRlcyBjb21vIDMyIGNpdWRhZGVzIGF1dG9yZXByZXNlbnRhZGFzIHkgNSByZWdpb25lcywgcG9yIGxvIHF1ZSBzZSBoYWNlIHVuYSByZWNvbGVjY2nDs24gZGUgMTYwIHNlcmllcyBkZSB0aWVtcG8gcXVlIHNpZ3VlbiB1bmEgZXN0cnVjdHVyYSBkZSBhZ3JlZ2FjacOzbiBqZXLDoXJxdWljYS4gICANCg0KIVtFc3F1ZW1hIEplcsOhcnF1aWNvXShHcmFmaWNvcy9SZWdpw7NuLmpwZyl7d2lkaHQ9MTAwJSxoZWlnaHQ9MTAwJX0gDQoNCkVsIG7Dum1lcm8gZGUgc2VyaWVzIGVuIGVsIG5pdmVsIGluZmVyaW9yIGVzIGRlIDE2MCBzZXJpZXMsIHBvciBsbyBxdWUgbGFzIG9ic2VydmFjaW9uZXMgZW4gZWwgbml2ZWwgw7psdGltbyBzdW1hcmFuIGEgbGFzIG9ic2VydmFjaW9uZXMgZGVsIG5pdmVsIGFudGVyaW9yIHkgYXPDrSBzdWNlc2l2YW1lbnRlLiAgIA0KDQpMb3MgNSBtb3Rpdm9zIGRlIGxhIGF1c2VuY2lhIHNlIHRyYW5zZm9ybWFuIGVuIHNlcmllcyBkZSB0aWVtcG8sIHBhcmEgYW5hbGl6YXJsb3MgY2FkYSB1bm8gcG9zdGVyaW9ybWVudGUuIExvcyBkYXRvcyBzZSBjb252aWVydGVuIGVuIG9iamV0b3MgZGUgc2VyaWVzIHRlbXBvcmFsZXMgKGB0c2ApIHV0aWxpemFuZG8gbGEgZnVuY2nDs24gYHRzYC4gQ2FkYSBzZXJpZSB0ZW1wb3JhbCBzZSBkZWZpbmUgY29uOg0KDQotIGBzdGFydCA9IDIwMDVgOiBFbCBwcmltZXIgYcOxbyBkZSBsYSBzZXJpZSB0ZW1wb3JhbCBlcyAyMDA1LiAgIA0KLSBgZW5kID0gMjAxOWA6IEVsIMO6bHRpbW8gYcOxbyBkZSBsYSBzZXJpZSB0ZW1wb3JhbCBlcyAyMDE5LiAgIA0KLSBgZnJlcXVlbmN5ID0gNGA6IExhIGZyZWN1ZW5jaWEgZGUgbGEgc2VyaWUgdGVtcG9yYWwgZXMgdHJpbWVzdHJhbCAoNCB0cmltZXN0cmVzIHBvciBhw7FvKS4gICAgDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCnRzLlRyYWJham8gPC0gdHMoVC5UcmFiYWpvICU+JSBzZWxlY3QoLiwgYygyOmxlbmd0aCguKSkpLCBzdGFydCA9IDIwMDUsIGVuZCA9IDIwMTksIGZyZXF1ZW5jeSA9IDQpDQp0cy5Fc3R1ZGlvIDwtIHRzKFQuRXN0dWRpbyAlPiUgc2VsZWN0KC4sIGMoMjpsZW5ndGgoLikpKSwgc3RhcnQgPSAyMDA1LCBlbmQgPSAyMDE5LCBmcmVxdWVuY3kgPSA0KQ0KdHMuVW5pb24gPC0gdHMoVC5VbmlvbiAlPiUgc2VsZWN0KC4sIGMoMjpsZW5ndGgoLikpKSwgc3RhcnQgPSAyMDA1LCBlbmQgPSAyMDE5LCBmcmVxdWVuY3kgPSA0KQ0KdHMuRGl2b3JjaW8gPC0gdHMoVC5EaXZvcmNpbyAlPiUgc2VsZWN0KC4sIGMoMjpsZW5ndGgoLikpKSwgc3RhcnQgPSAyMDA1LCBlbmQgPSAyMDE5LCBmcmVxdWVuY3kgPSA0KQ0KdHMuRmFtaWxpYSA8LSB0cyhULkZhbWlsaWEgJT4lIHNlbGVjdCguLCBjKDI6bGVuZ3RoKC4pKSksIHN0YXJ0ID0gMjAwNSwgZW5kID0gMjAxOSwgZnJlcXVlbmN5ID0gNCkNCmBgYA0KDQojIE1vdGl2byBkZSBsYSBhdXNlbmNpYTogYFRyYWJham9gDQoNClNlIGFuYWxpemEgY8OzbW8gY2FzbyBwYXJ0aWN1bGFyIGVsIG1vdGl2byBkZSBsYSAqKmF1c2VuY2lhIHBvciB0cmFiYWpvKiosIHBhcmEgZW1wZXphciAgZmFtaWxpYXJpemFyc2UgY29uIGxhIGplcmFycXVpemFjacOzbiBkZWwgbW9kZWxvIHkgcG9zdGVyaW9ybWVudGUgYWdyZWdhciBkZSBtYW5lcmEgZ2VuZXJhbCBsb3MgZGVtw6FzIG1vdGl2b3MgZXhwdWVzdG9zIGFsIGluaWNpby4gICAgIA0KDQpVdGlsaXphbmRvIGxhIGZ1bmNpw7NuIGBkeWdyYXBoYCBwZXJtaXRlIG9ic2VydmFyIGRlIG1hbmVyYSBpdGVyYXRpdmEgbXVsdGlwbGVzIHNlcmllcyBkZSB0aWVtcG8uICAgICANCg0KLSBgZHlSYW5nZVNlbGVjdG9yKClgOiBBZ3JlZ2EgdW4gc2VsZWN0b3IgZGUgcmFuZ28gKHVuIGNvbnRyb2wgZGVzbGl6YW50ZSkgcXVlIHBlcm1pdGUgYWwgdXN1YXJpbyBzZWxlY2Npb25hciB1biByYW5nbyBkZSBmZWNoYXMgcGFyYSB2aXN1YWxpemFyIGVuIGVsIGdyw6FmaWNvLiAgICANCi0gYGR5TGVnZW5kKHdpZHRoID0gNjUwKWA6IEHDsWFkZSB1bmEgbGV5ZW5kYSBhbCBncsOhZmljbyB5IGVzdGFibGVjZSBzdSBhbmNobyBhIDY1MCBww614ZWxlcy4gICANCi0gYGR5T3B0aW9ucyhjb2xvcnMgPSBSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwoMzIsICJTZXQyIikpYDogUGVyc29uYWxpemEgbG9zIGNvbG9yZXMgZGUgbGFzIHNlcmllcyBlbiBlbCBncsOhZmljbyB1dGlsaXphbmRvIGxhIHBhbGV0YSBkZSBjb2xvcmVzICJTZXQyIiBkZSBSQ29sb3JCcmV3ZXIsIHF1ZSBwcm9wb3JjaW9uYSB1bmEgcGFsZXRhIGRlIDMyIGNvbG9yZXMuICAgICANCi0gYGR5SGlnaGxpZ2h0KGhpZ2hsaWdodFNlcmllc09wdHMgPSBsaXN0KHN0cm9rZVdpZHRoID0gMikpYDogUGVybWl0ZSByZXNhbHRhciBsYXMgc2VyaWVzIGVuIGVsIGdyw6FmaWNvIGN1YW5kbyBlbCB1c3VhcmlvIHBhc2EgZWwgY3Vyc29yIHNvYnJlIGVsbGFzLiBgc3Ryb2tlV2lkdGggPSAyYCBlc3RhYmxlY2UgZWwgZ3Jvc29yIGRlIGxhIGzDrW5lYSByZXNhbHRhZGEgYSAyIHDDrXhlbGVzLiAgICAgDQoNCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpHLlRyYWJham8gPC0gZHlncmFwaCh0cy5UcmFiYWpvLCBtYWluID0gIlRyYWJham8iLCAgeWxhYiA9ICJNaWdyYW50ZXMiLCB4bGFiID0gIlBlcmlvZG8iKSAlPiUNCiAgICAgICAgICAgICAgZHlSYW5nZVNlbGVjdG9yKCkgJT4lDQogICAgICAgICAgICAgICBkeUxlZ2VuZCh3aWR0aCA9IDY1MCkgJT4lDQogICAgICAgICAgICAgICAgZHlPcHRpb25zKGNvbG9ycyA9IFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCgzMiwgIlNldDIiKSkgJT4lDQogICAgICAgICAgICAgICAgIGR5SGlnaGxpZ2h0KGhpZ2hsaWdodFNlcmllc09wdHMgPSBsaXN0KHN0cm9rZVdpZHRoID0gMikpDQpHLlRyYWJham8NCmBgYA0KDQpgYGB7ciwgb3V0LndpZHRoPSAiMTEwJSIsIGZpZy5hbGlnbj0nY2VudGVyJyxmaWcuY2FwPSAiTW90aXZvIGRlIHRyYWJham8iLCBldmFsID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJHcmFmaWNvcy9HcmFmaWNvIFRyYWJham8ucG5nIikNCmBgYA0KDQpBIGNvbnRpbnVhY2nDs24sIHNlIHByZXNlbnRhIGRlIG1hbmVyYSBkZXNhZ3JlZ2FkYSB1biBhbsOhbGlzaXMgZGVzY3JpcHRpdm8gZGUgbGFzIDMyIGNpdWRhZGVzIGF1dG9yZXByZXNlbnRhZGFzLiAgDQoNCmBgYHtyLGZpZy5hbGlnbj0nY2VudGVyJywgZWNobyA9IEZBTFNFfQ0KdGFibGEgPC0gbXlkYXRhWywgZ3JlcGwoIlRyYWJham8iLCBuYW1lcyhteWRhdGEpKV0NCg0Ka2FibGUoZGVzY3JpYmUodGFibGEpLA0KICAgICAgZGlnaXRzID0gMiwNCiAgICAgICBjYXB0aW9uID0gIkFuw6FsaXNpcyBkZXNjcmlwdGl2bzogTW90aXZvIGRlIHRyYWJham8iKSAlPiUNCiBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgDQogICAgICAgICAgICAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiY29uZGVuc2VkIiksDQogICAgICAgICAgICAgICBmb250X3NpemUgPSA4LA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSAiY2VudGVyIiwNCiAgICAgICAgICAgICAgIGxhdGV4X29wdGlvbnM9ICJIT0xEX3Bvc2l0aW9uIikgJT4lDQogIGthYmxlX2NsYXNzaWMoZnVsbF93aWR0aCA9IEYsIGh0bWxfZm9udCA9ICJDZW50dXJ5IEdvdGhpYyIpICU+JSANCiAgIGdzdWIoImZvbnQtc2l6ZTogaW5pdGlhbCAhaW1wb3J0YW50OyIsICJmb250LXNpemU6IDEwcHQgIWltcG9ydGFudDsiLCAuKSAlPiUNCiAgICBnc3ViKCJ0ZXh0LWFsaWduOiBpbml0aWFsICFpbXBvcnRhbnQ7IiwgInRleHQtYWxpZ246IGp1c3RpZnkgIWltcG9ydGFudDsiLCAuKQ0KYGBgDQoNCioqRWplbXBsbyoqOiBQb3IgY2F1c2FzIGRlIHRyYWJham8gbGEgY2l1ZGFkIGRlIEFjYXB1bGNvIG11ZXN0cmEgdW5hIG1lZGlhIGRlIDQuNjIgcGVyc29uYXMgcXVlIGVtaWdyYXJvbiBwb3IgdHJhYmFqbyBkZSBjYWRhIDEwMDAgcGVyc29uYXMuICAgDQoNCiMjIFNlcmllIGRlIHRpZW1wbyBqZXLDoXJxdWljYSAgIA0KDQpTZSB1dGlsaXphIGxhIGZ1bmNpw7NuIGBodHNgIHBhcmEgY3JlYXIgdW5hIHNlcmllIGRlIHRpZW1wbyBqZXLDoXJxdWljYS4gDQoNCioqRGVmaW5pY2nDs24gZGUgdmVjdG9yZXMqKjogIA0KDQotIGBSZWdpb25lc2A6IFVuIHZlY3RvciBxdWUgY29udGllbmUgY8OzZGlnb3MgZGUgcmVnaW9uZXMgcmVwZXRpZG9zIHBhcmEgY3JlYXIgdW5hIGV0aXF1ZXRhIGRlIHJlZ2nDs24gZXNwZWPDrWZpY2EuICANCi0gYENpdWRhZGVzYDogVW4gdmVjdG9yIHF1ZSBjb250aWVuZSBjw7NkaWdvcyBkZSBjaXVkYWRlcyBxdWUgc2UgY29tYmluYW4gY29uIGxhcyByZWdpb25lcyBwYXJhIGNyZWFyIG5vbWJyZXMgw7puaWNvcy4gIA0KLSBgTW90aXZvYDogVW4gdmVjdG9yIHF1ZSBjb250aWVuZSBlbCBtb3Rpdm8gIlRyYWJham8iLCByZXBldGlkbyBwYXJhIGlndWFsYXIgbGEgbG9uZ2l0dWQgZGUgbG9zIG90cm9zIHZlY3RvcmVzLiAgIA0KDQoqKkNyZWFjaW9uIGRlbCBub21icmUgZGUgY29sdW1uYXMqKiAgDQoNClNlIHV0aWxpemFuIGxvcyBkYXRvcyBkZSDDumx0aW1vIG5pdmVsIHkgc2UgdXRpbGl6YSBlbCBhcmd1bWVudG8gYGNoYXJhY3RlcnNgIGRvbmRlIGxvcyBwcmltZXJvcyBkb3MgY2FyYWN0ZXJlcyBjb3JyZXNwb25kZW4gYWwgcHJpbWVyIG5pdmVsIChgUmVnacOzbmApLCBsb3Mgc2lndWllbnRlcyBkb3MgY29ycmVzcG9uZGVuIGFsIHNlZ3VuZG8gbml2ZWwgKGBDaXVkYWRlc2ApIHkgY29tbyDDumx0aW1vIGxvcyBzaWV0ZSBjYXJhY3RlcmVzIGNvcnJlc3BvbmRlbiBhbCBtb3Rpdm8gZGUgbGEgYXVzZW5jaWEgKGBUcmFiYWpvYCkuICAgDQoNCi0gYGh0cyh0cy5UcmFiYWpvLCBub2RlcyA9IGxpc3QoMzIpLCBjaGFyYWN0ZXJzID0gYygyLCAyLCA3KSlgOiBDcmVhIHVuIG1vZGVsbyBqZXLDoXJxdWljbyBkZSBzZXJpZXMgdGVtcG9yYWxlcyAoYGh0c2ApIGEgcGFydGlyIGRlIHRzLlRyYWJham8uICAgIA0KLSBgbm9kZXMgPSBsaXN0KDMyKWA6IERlZmluZSB1biBzb2xvIG5pdmVsIGVuIGxhIGplcmFycXXDrWEgKGBuaXZlbCAxYCkgY29uIDMyIG5vZG9zLiAgICAgDQotIGBjaGFyYWN0ZXJzID0gYygyLCAyLCA3KWA6IERlZmluZSBsYSBlc3RydWN0dXJhIGRlIGxvcyBub21icmVzIGRlIGxhcyBjb2x1bW5hcyBlbiB0w6lybWlub3MgZGUgY2FyYWN0ZXJlcyBwYXJhIGxhIGByZWdpw7NuKDIpYCwgYGNpdWRhZCgyKWAgeSBgbW90aXZvKDcpYC4gICAgDQotIGBNb2RlbG8xJGxhYmVscyRMZXZlbCAxIDwtIGMoIkNlbnRybyIsICJOb3Jlc3RlIiwgIk5vcm9lc3RlIiwgIlN1cmVzdGUiLCAiT2NjaWRlbnRlIilgOiBBc2lnbmEgZXRpcXVldGFzIGEgbG9zIG5vZG9zIGVuIGVsICpuaXZlbCAxKiBkZWwgbW9kZWxvIE1vZGVsbzEuIEVzdGFzIGV0aXF1ZXRhcyByZXByZXNlbnRhbiBkaWZlcmVudGVzIHJlZ2lvbmVzIG8gw6FyZWFzIGdlb2dyw6FmaWNhcyBlbiBsdWdhciBkZSBsb3MgY8OzZGlnb3Mgb3JpZ2luYWxlcy4gICAgIA0KDQoNCmBgYHtyLCBlY2hvID1UUlVFfQ0KI0NhbWJpYW1vcyBsb3Mgbm9tYnJlcyBkZSBsYXMgY29sdW1uYXMgDQpSZWdpb25lcyA8LSBjKHJlcCgiQ0UiLCA3KSwNCiAgICAgICAgICAgICAgcmVwKCJORSIsIDUpLCANCiAgICAgICAgICAgICAgcmVwKCJOVyIsIDUpLCANCiAgICAgICAgICAgICAgcmVwKCJXRSIsIDgpLA0KICAgICAgICAgICAgICByZXAoIlNPIiwgNykpDQpDaXVkYWRlcyA8LSBjKCIxMSIsIAkiMjQiLCAJIjAxIiwgICIzMiIsIAkiMDQiLCAJIjE0IiwgCSIyOSIsIAkNCiAgICAgICAgICAgICAgIjIxIiwgCSIwMyIsIAkiMDYiLCAJIjE1IiwgCSIwOSIsIAkNCiAgICAgICAgICAgICAgIjA4IiwgCSIxOSIsIAkiMjAiLCAJIjMwIiwgCSIxOCIsIAkNCiAgICAgICAgICAgICAgIjEyIiwgCSIyNyIsIAkiMDIiLCAJIjA1IiwgCSIxMyIsIAkiMjgiLCAJIjIyIiwgCSIyNiIsIAkNCiAgICAgICAgICAgICAgIjMxIiwgCSIyMyIsIAkiMDciLCAJIjI1IiwgCSIxNyIsIAkiMTAiLCAJIjE2IikNCk1vdGl2byA8LSBjKHJlcCgiVHJhYmFqbyIsIDMyKSkNCg0Kbm9tYnJlcyA8LSBwYXN0ZTAoUmVnaW9uZXMsIENpdWRhZGVzLCBNb3Rpdm8pICMjIExhcmdvIGRlIDExIC9SZWdpb25lcz0yLENpdWRhZGVzPTIsTW90aXZvPTcNCmNvbG5hbWVzKHRzLlRyYWJham8pIDwtIG5vbWJyZXMNCg0KI05vZG9zIA0KTW9kZWxvMSA8LSBodHModHMuVHJhYmFqbywgbm9kZXMgPSBsaXN0KDMyKSwgY2hhcmFjdGVycyA9IGMoMiwgMiwgNykpDQoNCiMjIENhbWJpYW1vcyBsYXMgZXRpcXVldGFzIA0KTW9kZWxvMSRsYWJlbHMkYExldmVsIDFgIDwtIGMoIkNlbnRybyIsICJOb3Jlc3RlIiwgIk5vcm9lc3RlIiwgIlN1cmVzdGUiLCAiT2NjaWRlbnRlIikNCmBgYA0KDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCmNsYXNzKE1vZGVsbzEpDQpzdW1tYXJ5KE1vZGVsbzEpDQojcDwtc21hdHJpeChNb2RlbG8xKSAjUmVzdW1lbiBkZSBsYSBtYXRyaXogZGUgaGllcmFycXVpY2FsIHRpbWUgc2VyaWVzDQojcTwtYWxsdHMoTW9kZWxvMSkgI01hdHJpeCBkZSB0b2RvcyBsb3Mgbml2ZWxlcw0KYGBgDQoNCiMjIE5pdmVsIDE6IFJlZ2nDs24gDQoNClNlIHZpc3VhbGl6YW4gbGFzIHNlcmllcyB0ZW1wb3JhbGVzIGFncmVnYWRhcyBkZSB1biBtb2RlbG8gamVyw6FycXVpY28gZGUgc2VyaWVzIHRlbXBvcmFsZXMgKGBNb2RlbG8xYCkuICAgDQoNCi0gYGFnZ3RzKGxldmVsID0gMSlgOiBFeHRyYWUgbGFzIHNlcmllcyB0ZW1wb3JhbGVzIGFncmVnYWRhcyBkZWwgbml2ZWwgMSBkZWwgbW9kZWxvIE1vZGVsbzEuIEVsIGBsZXZlbCA9IDEgYGluZGljYSBxdWUgc2UgZXN0w6EgZXh0cmF5ZW5kbyBkYXRvcyBkZWwgbml2ZWwgbcOhcyBhbHRvIGVuIGxhIGplcmFycXXDrWEuICAgICAgDQoNCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0KTW9kZWxvMSAlPiUgDQogYWdndHMobGV2ZWwgPSAxKSAlPiUNCiAgYXV0b3Bsb3Qoc2l6ZSA9IDEpICsgDQogICB0aGVtZV9jbGFzc2ljKCkgKyANCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwNCiAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuNSwgImxpbmVzIikpICsNCiAgICAgc2NhbGVfY29sb3JfdmlyaWRpc19kKCkgKyANCiAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwoNSwgIkRhcmsyIikpICsgDQogICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA1LCAyMDE5LCBieSA9IDMpKSArDQogICAgICAgIGxhYnModGl0bGUgPSAiTW90aXZvIGRlIGxhIGF1c2VuY2lhIDIwMDUtMjAxOSIsDQogICAgICAgICAgICAgc3VidGl0bGUgPSAiVHJhYmFqbyIsDQogICAgICAgICAgICAgeSA9ICJSYXRlIiwNCiAgICAgICAgICAgICB4ID0gICJZZWFyIiwNCiAgICAgICAgICAgICBjb2xvciA9ICJTZXJpZXMiKSANCmBgYA0KDQpMYSBncsOhZmljYSBzdXBlcmlvciBtdWVzdHJhIGxhIHRhc2EgZGUgbWlncmFjacOzbiBwb3IgdHJhYmFqbyB0b3RhbCBwb3IgcmVnacOzbi4gRG9uZGUgc2UgcHVlZGUgYXByZWNpYXIgcXVlIGxhIHJlZ2nDs24gTm9yZXN0ZSB5IE5vcm9lc3RlIHByZXNlbnRhbiB1bmEgbWVub3IgbW9pdmlsaWRhZCBjb24gcmVzcGVjdG8gYSBsYXMgZGVtw6FzLiANCg0KDQojIyBOaXZlbCAyOiBDaXVkYWQgYXV0b3JlcHJlc2VudGFkYQ0KDQpBIGNvbnRpbnVhY2nDs24gc2UgbXVldHJhbiBsb3MgZGF0b3MgZGVzZ2xvc2Fkb3MgcG9yIGxhcyAzMiBjaXVkYWRlcy4gDQoNCi0gYGFnZ3RzKGxldmVsID0gMilgOiBpbmRpY2EgcXVlIHNlIGVzdMOhbiBleHRyYXllbmRvIGRhdG9zIGRlIHVuIG5pdmVsIGRlIGplcmFycXXDrWEgaW5mZXJpb3IgYWwgbml2ZWwgMS4gIA0KDQpgYGB7cn0NCk1vZGVsbzEgJT4lIA0KIGFnZ3RzKGxldmVsID0gMikgJT4lDQogIGF1dG9wbG90KHNpemUgPSAwLjUpICsgDQogICB0aGVtZV9jbGFzc2ljKCkgKyANCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgZmFtaWx5ID0gIkNlbnR1cnkgR290aGljIiksDQogICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhbWlseSA9ICJDZW50dXJ5IEdvdGhpYyIpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4LCBmYW1pbHkgPSAiQ2VudHVyeSBHb3RoaWMiKSwNCiAgICAgICAgICBsZWdlbmQuc3BhY2luZy54ID0gdW5pdCgwLjEsICJjbSIpLA0KICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAibGluZXMiKSwNCiAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKw0KICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDgsICJEYXJrMiIpKSg2MCkpICsgDQogICAgICBndWlkZXMoY29sID0gZ3VpZGVfbGVnZW5kKG5jb2wgPSAxNSkpICsNCiAgICAgICBsYWJzKHRpdGxlID0gIk1vdGl2byBkZSBsYSBhdXNlbmNpYSAyMDA1LTIwMTkiLA0KICAgICAgICAgICAgc3VidGl0bGUgPSAiVHJhYmFqbyIsDQogICAgICAgICAgICB5ID0gIlJhdGUiLA0KICAgICAgICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICAgICAgIGNvbG9yID0gIlNlcmllcyIpIA0KYGBgDQoNClNpIGJpZW4gbGEgZ3LDoWZpY2EgYW50ZXJpb3Igbm8gcGVybWl0ZSBzdSBpbnRlcnByZXRhYmlsaWRhZCBkZWJpZG8gYSBxdWUgdG9kbyBlbCBlbnNhbWJsZSBkZSBsYXMgc2VyaWVzIGVzdMOhbiBtdXkganVudGFzLiANCg0KSGFjaWVuZG8gdXNvIGRlIGxhIGZ1bmNpw7NuIGBhZ2d0c2AgZXh0cmFlIGxhcyBzZXJpZXMgdGVtcG9yYWxlcyBkZSB1biBvYmpldG8gYGh0c2AgcGFyYSBjdWFscXVpZXIgbml2ZWwgZGUgZGVzYWdyZWdhY2nDs24uIFBhcmEgYGFnZ3RzKE1vZGVsbzEsIGxldmVsID0gMilgLCBzZSBlc3BlY2lmaWNhIHF1ZSBxdWVyZW1vcyBleHRyYWVyIGxhcyBzZXJpZXMgdGVtcG9yYWxlcyBkZWwgbml2ZWwgMiBkZWwgbW9kZWxvIGplcsOhcnF1aWNvLiBMb3Mgbml2ZWxlcyBlbiB1biBtb2RlbG8gamVyw6FycXVpY28gY29ycmVzcG9uZGVuIGEgZGlmZXJlbnRlcyBuaXZlbGVzIGRlIGFncmVnYWNpw7NuIGVuIGxhIGplcmFycXXDrWEgZGUgZGF0b3MuICAgDQoNClBhcmEgZXN0ZSBjYXNvLCBzZSBlc3TDoW4gdHJhYmFqYW5kbyBjb24gZG9zIG5pdmVsZXMgZGUgZGVzYWdyZWdhY2nDs24gKFJlZ2lvbmVzIHkgQ2l1ZGFkZXMpIHkgYmllbiB1biBOaXZlbCBDZXJvIChUb3RhbCkuICAgDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCmdyb3VwcyA8LSBhZ2d0cyhNb2RlbG8xLCBsZXZlbCA9IDIpDQpgYGANCg0KRW4gZWwgc2lndWllbnRlIGdyw6FmaWNvIHNlIG11ZXN0cmFuIGxhcyBzZXJpZXMgZGUgdGllbXBvIGRlbCBuaXZlbCBpbmZlcmlvciwgZXMgZGVjaXIsIGxhcyB0YXNhcyBkZSBtaWdyYWNpw7NuIHBvciB0cmFiYWpvIHBhcmEgY2FkYSB1bmEgZGUgbGFzIGNpdWRhZGVzIGVuIHN1cyByZXNwZWN0aXZhcyByZWdpb25lcy4gICAgDQoNCkF5dWRhbmRvIGFzw60gYSB2aXN1YWxpemFyIGRlIG1hbmVyYSBpbmRpdmlkdWFsIGxhcyBzZXJpZXMuICAgIA0KDQpgYGB7ciwgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDV9DQp0aWJibGU6OmFzX3RpYmJsZShncm91cHMpICU+JQ0KIHRpZHlyOjpnYXRoZXIoU2VyaWVzKSAlPiUNCiAgbXV0YXRlKERhdGUgPSByZXAodGltZShncm91cHMpLCBOQ09MKGdyb3VwcykpLA0KICAgICAgICAgR3JvdXAgPSBzdHJpbmdyOjpzdHJfZXh0cmFjdChTZXJpZXMsICIoW0EtWmEteiBdKikiKSkgJT4lDQogICBnZ3Bsb3QoYWVzKHggPSBEYXRlLCB5ID0gdmFsdWUsIGdyb3VwID0gU2VyaWVzLCBjb2xvdXIgPSBTZXJpZXMpKSArDQogICAgZ2VvbV9saW5lKCkgKyANCiAgICAgdGhlbWVfY2xhc3NpYygpICsNCiAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLCBmYW1pbHkgPSAiQ2VudHVyeSBHb3RoaWMiKSwNCiAgICAgICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYW1pbHkgPSAiQ2VudHVyeSBHb3RoaWMiKSwNCiAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSwgZmFtaWx5ID0gIkNlbnR1cnkgR290aGljIiksDQogICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwgZmFtaWx5ID0gIkNlbnR1cnkgR290aGljIiksDQogICAgICAgICAgICBsZWdlbmQuc3BhY2luZy54ID0gdW5pdCgwLjEsICJjbSIpLA0KICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICJsaW5lcyIpLA0KICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsNCiAgICAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2QoKSArIA0KICAgICAgICNzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDgsICJTZXQyIikpKDMzKSkgKyANCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxOTgwLCAyMDE1LCBieSA9IDUpKSArDQogICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkgKw0KICAgICAgICAgIGd1aWRlcyhjb2wgPSBndWlkZV9sZWdlbmQobmNvbCA9IDE1KSkgKw0KICAgICAgICAgICBsYWJzKHRpdGxlID0gIk1vdGl2byBkZSBsYSBhdXNlbmNpYSAyMDA1LTIwMTkiLA0KICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gIlRyYWJham8iLA0KICAgICAgICAgICAgICAgIHkgPSAiUmF0ZSIsDQogICAgICAgICAgICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICAgICAgICAgICBjb2xvciA9ICJHcnVwb3MiKSArDQogICAgICAgICAgICBmYWNldF93cmFwKC4gfiBHcm91cCkNCmBgYA0KDQojIyBGb3JlY2FzdGluZzogTW90aXZvIGRlIHRyYWJham8NCg0KVXRpbGl6YW5kbyBsYSBmdW5jacOzbiBgZm9yZWNhc3QoKWAgZGVsIHBhcXVldGUgYGh0c2AuICANCg0KU2UgcHJlc2VudGFuIHRyZXMgb3BjaW9uZXMgaW50ZWdyYWRhcyBwYXJhIHByb2R1Y2lyIHByb27Ds3N0aWNvcyB1c2FuZG8gZWwgcGFyw6FtZXRybyBgZm1ldGhvZGA6IA0KDQotICoqRVRTKiogYEV4cG9uZW50aWFsIFNtb290aGluZ2AsICAgDQotIE1vZGVsb3MgYEFSSU1BYCANCi0gQ2FtaW5hdGFzIGFsZWF0b3JpYXMoYFJXYCkuICAgICANCg0KIyMjIEVuZm9xdWVzIFteMl0NClteMl06KEZvcmVjYXN0aW5nIEhpZXJhcmNoaWNhbCBUaW1lIFNlcmllcyB1c2luZyBSIC0gQnJpbGxpbyBEYXRhIFNjaWVuY2UgLSBNZWRpdW0uIChuLmQuKS4gUmV0cmlldmVkIE1hcmNoIDMxLCAyMDIwLCBmcm9tIGh0dHBzOi8vbWVkaXVtLmNvbS9icmlsbGlvLWRhdGEtc2NpZW5jZS9mb3JlY2FzdGluZy1oaWVyYXJjaGljYWwtdGltZS1zZXJpZXMtdXNpbmctci01OTg4MjhkYmE0MzUpDQoNCi0gKkVuZm9xdWUgZGUgYWJham8gaGFjaWEgYXJyaWJhKiAqKiJib3R0b20tdXAiKiooYG1ldGhvZD0gImJ1ImApOiBQcm9ub3N0aWNhIGRlbCBuaXZlbCBtw6FzIGJham8gZGUgbGEgamVyYXJxdcOtYSwgZXMgZGVjaXIsIGxvcyBtb3Rpdm9zIGRlIGF1c2VuY2lhIHkgbHVlZ28gdmEgYWdyZWdhbmRvIGxvcyByZXN1bHRhZG9zIGEgbGEgamVyw6FycXXDrWEgZ2VuZXJhciBlbCBwcm9ub3N0aWNvIGRlbCBuaXZlbCBzdXBlcmlvciBhbCDDumx0aW1vLiAgIA0KDQotICpFbmZvcXVlIGRlIGFycmliYSBoYWNpYSBhYmFqbyogKioidG9wLWRvd24iKiogKGBtZXRob2Q9ICJ0ZGZwImApOiBQcm9ub3N0aWNhIGVuIGxhIGplcmFycXXDrWEgZGVsIG5pdmVsIG3DoXMgYWx0bywgZXMgZGVjaXIsIHBvciByZWdpb25lcyB5IGx1ZWdvIHZhIGRlc2dsb3NhbmRvIGxvcyByZXN1bHRhZG9zIGVuIGxhIGplcmFycXXDrWEuICAgIA0KDQotICpFbmZvcXVlIGludGVybWVkaW8qICoqIm1pZGRsZS1vdXQiIChgbWV0aG9kPSAibW8iYCk6IENvbWJpbmEgZW5mb3F1ZXMgYXNjZW5kZW50ZXMgeSBkZXNjZW5kZW50ZXMuIFByaW1lcm8sIHNlIGVsaWdlIHVuICJuaXZlbCBtZWRpbyIgeSBzZSBnZW5lcmFuIHByb27Ds3N0aWNvcyBwYXJhIHRvZGFzIGxhcyBzZXJpZXMgZW4gZXN0ZSBuaXZlbC4gUGFyYSBsYXMgc2VyaWVzIHBvciBlbmNpbWEgZGVsIG5pdmVsIG1lZGlvLCBzZSBnZW5lcmFuIHByb27Ds3N0aWNvcyBjb2hlcmVudGVzIHV0aWxpemFuZG8gZWwgZW5mb3F1ZSBkZSBhYmFqbyBoYWNpYSBhcnJpYmEgYWdyZWdhbmRvIGxvcyBwcm9uw7NzdGljb3MgZGUgIm5pdmVsIG1lZGlvIiBoYWNpYSBhcnJpYmEuIFBhcmEgbGFzIHNlcmllcyBwb3IgZGViYWpvIGRlbCAibml2ZWwgbWVkaW8iLCBzZSBnZW5lcmFuIHByb27Ds3N0aWNvcyBjb2hlcmVudGVzIHV0aWxpemFuZG8gdW4gZW5mb3F1ZSBkZSBhcnJpYmEgaGFjaWEgYWJham8gYWwgZGVzZ2xvc2FyIGxvcyBwcm9uw7NzdGljb3MgZGUgIm5pdmVsIG1lZGlvIiBoYWNpYSBhYmFqby4gICAgICAgIA0KLSBgbWV0aG9kID0gInRkZnAiYDogRXNwZWNpZmljYSBlbCBtw6l0b2RvIGRlIHByb27Ds3N0aWNvIGEgdXRpbGl6YXIuICJ0ZGZwIiBzZSByZWZpZXJlIGEgInRvcC1kb3duIGZvcmVjYXN0aW5nIHVzaW5nIGEgZGV0YWlsZWQgZm9yZWNhc3QgcHJvY2VkdXJlIi4gRXN0ZSBtw6l0b2RvIHJlYWxpemEgZWwgcHJvbsOzc3RpY28gYSBuaXZlbCBtw6FzIGRldGFsbGFkbyBwcmltZXJvIHkgbHVlZ28gYWdyZWdhIGxvcyBwcm9uw7NzdGljb3MgaGFjaWEgbG9zIG5pdmVsZXMgc3VwZXJpb3JlcyBkZSBsYSBqZXJhcnF1w61hLiAgICANCi0gYGggPSA0YDogRGVmaW5lIGVsIGhvcml6b250ZSBkZSBwcm9uw7NzdGljby4gRW4gZXN0ZSBjYXNvLCBzZSBlc3TDoSBwcm9ub3N0aWNhbmRvIDQgcGVyw61vZG9zIGhhY2lhIGVsIGZ1dHVyby4gICAgDQotIGBrZWVwLmZpdHRlZCA9IFRSVUVgOiBNYW50aWVuZSBsb3MgdmFsb3JlcyBhanVzdGFkb3MgZGVsIG1vZGVsbyBwYXJhIHN1IGFuw6FsaXNpcyBwb3N0ZXJpb3IsIGxvIGN1YWwgcHVlZGUgc2VyIMO6dGlsIHBhcmEgZXZhbHVhciBlbCByZW5kaW1pZW50byBkZWwgbW9kZWxvLiAgICANCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0KI2g8PC1mb3JlY2FzdCBob3Jpem9uDQojbWV0aG9kPSAibW8iPDwtIm1pZGRsZS1vdXQiDQpmLm1vZGVsbzEgPC0gZm9yZWNhc3QoTW9kZWxvMSwgaCA9IDQsIG1ldGhvZCA9ICJ0ZGZwIiwgZm1ldGhvZCA9ICJldHMiLCBwYXJhbGxlbCA9IFRSVUUsIGtlZXAuZml0dGVkID0gVFJVRSkNCmBgYA0KDQpgYGB7cixlY2hvID0gVFJVRX0NCmNsYXNzKGYubW9kZWxvMSkNCiNzdW1tYXJ5KGYubW9kZWxvMSkNCmBgYA0KDQojIyMgTml2ZWwgMCBhbCAyICAgIA0KDQpTZSBleHRyYWVuIGxhcyBzZXJpZXMgdGVtcG9yYWxlcyBwYXJhIGxvcyBuaXZlbGVzIDAsIDEgeSAyIHRhbnRvIGRlbCBtb2RlbG8gZGUgcHJvbsOzc3RpY28gKGBmY3N0MWApIGNvbW8gZGVsIG1vZGVsbyBvcmlnaW5hbCAoYGdyb3Vwc2ApLiBFc3RvIHRlIHBlcm1pdGlyw6EgY29tcGFyYXIgbG9zIGRhdG9zIG9yaWdpbmFsZXMgY29uIGxvcyBwcm9uw7NzdGljb3MgZ2VuZXJhZG9zIGEgZGlmZXJlbnRlcyBuaXZlbGVzIGRlIGxhIGplcmFycXXDrWEuICAgIA0KLSBgbGV2ZWxzID0gMDoyYDogRXNwZWNpZmljYSBxdWUgc2UgZGViZW4gZXh0cmFlciBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgcGFyYSBsb3Mgbml2ZWxlcyAwLCAxIHkgMiBkZWwgbW9kZWxvIGplcsOhcnF1aWNvLiAgICANCg0KYGBge3IsZWNobyA9IFRSVUV9DQpmY3N0MSA8LSBhZ2d0cyhmLm1vZGVsbzEsIGxldmVscyA9IDA6MikNCmdyb3VwcyA8LSBhZ2d0cyhNb2RlbG8xLCBsZXZlbHMgPSAwOjIpDQpgYGANCg0KU2UgdmlzdWFsaXphbiB0YW50byBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgcHJvbm9zdGljYWRhcyAoZmNzdDEpIGNvbW8gbGFzIHNlcmllcyB0ZW1wb3JhbGVzIG9yaWdpbmFsZXMgKGdyb3VwcykuICAgDQoNCmBgYHtyLGZpZy53aWR0aCA9IDgsZmlnLmhlaWdodCA9IDV9DQphdXRvcGxvdChmY3N0MSwgc2l6ZSA9IDAuNSkgKw0KIGF1dG9sYXllcihncm91cHMpICsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMjAxOSwgY29sb3IgPSAiI0E4QUJENyIsIGxpbmV0eXBlPSAiZGFzaGVkIikgKw0KICAgdGhlbWVfY2xhc3NpYygpICsNCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCwgZmFtaWx5ID0gIkNlbnR1cnkgR290aGljIiksDQogICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhbWlseSA9ICJDZW50dXJ5IEdvdGhpYyIpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3LCBmYW1pbHkgPSAiQ2VudHVyeSBHb3RoaWMiKSwNCiAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuNSwgImxpbmVzIiksDQogICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsNCiAgICAgc2NhbGVfY29sb3JfdmlyaWRpc19kKCkgKyANCiAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNSwgMjAyNSwgYnkgPSAyKSkgKw0KICAgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKSArDQogICAgICAgIGd1aWRlcyhjb2wgPSBndWlkZV9sZWdlbmQobmNvbCA9IDE1KSkrDQogICAgICAgICBsYWJzKHRpdGxlID0gIk1vdGl2byBkZSBsYSBhdXNlbmNpYSAyMDA1LTIwMTkiLA0KICAgICAgICAgICAgICBzdWJ0aXRsZSA9ICJUcmFiYWpvIiwNCiAgICAgICAgICAgICAgeSA9ICJSYXRlIiwNCiAgICAgICAgICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICAgICAgICAgY29sb3IgPSAiU2VyaWVzIikgDQpgYGANCg0KQWhvcmEgYmllbiwgc2UgY29tYmluYW4gbGFzIHNlcmllcyB0ZW1wb3JhbGVzIG9yaWdpbmFsZXMgeSBsb3MgcHJvbsOzc3RpY29zIGVuIHVuYSBzb2xhIHNlcmllIHRlbXBvcmFsLCBtYW50ZW5pZW5kbyBsYSBtaXNtYSBmcmVjdWVuY2lhIHkgcHVudG8gZGUgcGFydGlkYSBxdWUgbGFzIHNlcmllcyBvcmlnaW5hbGVzLiAgDQoNCmBgYHtyLGVjaG8gPSBUUlVFfQ0KdGFibGEgPC0gdHMocmJpbmQoZ3JvdXBzLCBmY3N0MSksIHN0YXJ0ID0gc3RhcnQoZ3JvdXBzKSwgZnJlcXVlbmN5ID0gNCkNCmBgYA0KDQojIyMgTml2ZWwgVG90YWw6IFBvciBtb3Rpdm8gZGUgdHJhYmFqbyAgIA0KDQpBIGNvbnRpbnVhY2nDs24gc2UgbXVldHJhbiBsb3MgZGF0b3MgZGVzZ2xvc2Fkb3MgYSBuaXZlbCBOYWNpb25hbC4gICAgDQoNCmBgYHtyfQ0KI2h0dHA6Ly93d3cuc3RoZGEuY29tL2VuZ2xpc2gvd2lraS9nZ3Bsb3QyLWxpbmUtdHlwZXMtaG93LXRvLWNoYW5nZS1saW5lLXR5cGVzLW9mLWEtZ3JhcGgtaW4tci1zb2Z0d2FyZQ0KYXV0b3Bsb3QodGFibGFbLCAiVG90YWwiXSwgY29sb3VyID0gICIjMTcyMEI3Iiwgc2l6ZSA9IDEuMiwgYWxwaGEgPSAwLjYsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAyMDE5LjUsIGNvbG9yID0gIiNBOEFCRDciLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDUsIDIwMjUsIGJ5ID0gMikpICsNCiAgICBsYWJzKHRpdGxlID0gIk1vdGl2byBkZSBsYSBhdXNlbmNpYSAyMDA1LTIwMTkiLA0KICAgICAgICAgc3VidGl0bGUgPSAiVHJhYmFqbyIsDQogICAgICAgICB5ID0gIlJhdGUiLA0KICAgICAgICAgeCA9ICAiWWVhciIsDQogICAgICAgICBjb2xvciA9ICJTZXJpZXMiKSANCmBgYA0KDQpgYGB7cixmaWcud2lkdGggPSAxMCxmaWcuaGVpZ2h0ID0gNX0NCmFzX3RpYmJsZSh0YWJsYVssLTFdKSAlPiUNCiB0aWR5cjo6Z2F0aGVyKFNlcmllcykgJT4lDQogIG11dGF0ZShEYXRlID0gcmVwKHRpbWUodGFibGEpLCBOQ09MKHRhYmxhKS0xKSwNCiAgICAgICAgIEdyb3VwID0gc3RyX2V4dHJhY3QoU2VyaWVzLCAiKFtBLVphLXogXSopIikpICU+JQ0KICAgZ2dwbG90KGFlcyh4ID0gRGF0ZSwgeSA9IHZhbHVlLCBncm91cCA9IFNlcmllcywgY29sb3VyID0gU2VyaWVzKSkgKw0KICAgIGdlb21fbGluZSgpICsNCiAgICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMjAxNywgY29sb3IgPSAiI0E4QUJENyIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIA0KICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4LCBmYW1pbHkgPSAiQ2VudHVyeSBHb3RoaWMiKSwNCiAgICAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFtaWx5ID0gIkNlbnR1cnkgR290aGljIiksDQogICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxLCBmYW1pbHkgPSAiQ2VudHVyeSBHb3RoaWMiKSwNCiAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwgZmFtaWx5ID0gIkNlbnR1cnkgR290aGljIiksDQogICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICJsaW5lcyIpKSArDQogICAgICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZCgpICsNCiAgICAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTk4NSwgMjAyNSwgYnkgPSAxMCkpICsNCiAgICAgICAgICBndWlkZXMoY29sID0gZ3VpZGVfbGVnZW5kKG5jb2wgPSAxNSkpKw0KICAgICAgICAgICBsYWJzKHRpdGxlID0gIk1vdGl2byBkZSBsYSBhdXNlbmNpYSAyMDA1LTIwMTkiLA0KICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gIlRyYWJham8iLA0KICAgICAgICAgICAgICAgIHkgPSAiUmF0ZSIsDQogICAgICAgICAgICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICAgICAgICAgICBjb2xvciA9ICJTZXJpZXMiKSArDQogICAgICAgICAgICBmYWNldF93cmFwKC5+R3JvdXApIA0KYGBgDQoNClNlIGV4dHJhZW4gbGFzIHNlcmllcyB0ZW1wb3JhbGVzIHBhcmEgbG9zIG5pdmVsZXMgMCwgMSB5IDIgdGFudG8gZGVsIG1vZGVsbyBkZSBwcm9uw7NzdGljbyAoYGYubW9kZWxvMWApLiBFc3RvIHRlIHBlcm1pdGlyw6EgY29tcGFyYXIgbG9zIGRhdG9zIG9yaWdpbmFsZXMgY29uIGxvcyBwcm9uw7NzdGljb3MgZ2VuZXJhZG9zIGEgZGlmZXJlbnRlcyBuaXZlbGVzIGRlIGxhIGplcmFycXXDrWEuIA0KDQotIGBsZXZlbHMgPSAwOjJgOiBFc3BlY2lmaWNhIHF1ZSBzZSBkZWJlbiBleHRyYWVyIGxhcyBzZXJpZXMgdGVtcG9yYWxlcyBwYXJhIGxvcyBuaXZlbGVzIDAsIDEgeSAyIGRlbCBtb2RlbG8gamVyw6FycXVpY28uICAgICAgDQoNCmBgYHtyLGV2YWw9RkFMU0V9DQpmLm1vZGVsbzEgJT4lIA0KIGFnZ3RzKGxldmVscyA9IDA6MikgJT4lDQogIGF1dG9wbG90KGZhY2V0ID0gRkFMU0UpICsgDQogICB0aGVtZV9jbGFzc2ljKCkgKw0KICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4LCBmYW1pbHkgPSAiQ2VudHVyeSBHb3RoaWMiKSwNCiAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFtaWx5ID0gIkNlbnR1cnkgR290aGljIiksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcsIGZhbWlseSA9ICJDZW50dXJ5IEdvdGhpYyIpLA0KICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAibGluZXMiKSkgKw0KICAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2QoKSArDQogICAgICBsYWJzKHRpdGxlID0gIk1vdGl2byBkZSBsYSBhdXNlbmNpYSAyMDA1LTIwMTkiLA0KICAgICAgICAgICBzdWJ0aXRsZSA9ICJUcmFiYWpvIiwNCiAgICAgICAgICAgeSA9ICJSYXRlIiwNCiAgICAgICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICAgICAgY29sb3IgPSAiU2VyaWVzIikNCmBgYA0KDQojIE1vdGl2b3MgZGUgYXVzZW5jaWEgZW4gZ2VuZXJhbA0KDQpVdGlsaXphbmRvIGxvcyA1IG1vdGl2b3MgZGUgYXVzZW5jaWE6IA0KLSBUcmFiYWpvICAgICANCi0gRXN0dWRpbyAgIA0KLSBTZSBjYXPDsyBvIHVuacOzICAgICANCi0gU2Ugc2VwYXLDsyBvIGRpdm9yY2nDsyAgICANCi0gUmV1bmlyc2UgY29uIGxhIGZhbWlsaWEgIA0KDQoqKlNlcmllIGRlIHRpZW1wbyoqICANCg0KTG9zIGRhdG9zIGRlIGxhIGVzdHJ1Y3R1cmEgZ2VuZXJhbCBzZSBjb252aWVydGVuIGVuIG9iamV0b3MgZGUgc2VyaWVzIHRlbXBvcmFsZXMgKGB0c2ApIHV0aWxpemFuZG8gbGEgZnVuY2nDs24gYHRzYC4gQ2FkYSBzZXJpZSB0ZW1wb3JhbCBzZSBkZWZpbmUgY29uOiAgICANCg0KLSBgc3RhcnQgPSAyMDA1YDogRWwgcHJpbWVyIGHDsW8gZGUgbGEgc2VyaWUgdGVtcG9yYWwgZXMgMjAwNS4gICANCi0gYGVuZCA9IDIwMTlgOiBFbCDDumx0aW1vIGHDsW8gZGUgbGEgc2VyaWUgdGVtcG9yYWwgZXMgMjAxOS4gICANCi0gYGZyZXF1ZW5jeSA9IDRgOiBMYSBmcmVjdWVuY2lhIGRlIGxhIHNlcmllIHRlbXBvcmFsIGVzIHRyaW1lc3RyYWwgKDQgdHJpbWVzdHJlcyBwb3IgYcOxbykuICAgDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCnRzLm15ZGF0YSA8LSB0cyhteWRhdGEgJT4lIHNlbGVjdCguLCBjKDI6bmNvbCguKSkpLCBzdGFydCA9IDIwMDUsIGVuZCA9IDIwMTksIGZyZXF1ZW5jeSA9IDQpDQpgYGANCg0KIyMgU2VyaWVzIGRlIHRpZW1wbyBwb3IgbW90aXZvcyBkZSBsYSBtaWdyYWNpw7NuICAgDQoNCiMjIyBNb3Rpdm8gZGUgdHJhYmFqbyAgDQoNCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpHLlRyYWJham8gPC0gZHlncmFwaCh0cy5UcmFiYWpvLCBtYWluID0gIlRyYWJham8iLCB5bGFiID0gIk1pZ3JhbnRlcyIsIHhsYWIgPSAiUGVyaW9kbyIpICU+JQ0KICAgICAgICAgICAgICBkeVJhbmdlU2VsZWN0b3IoKSAlPiUNCiAgICAgICAgICAgICAgIGR5TGVnZW5kKHdpZHRoID0gNjUwKSAlPiUNCiAgICAgICAgICAgICAgICBkeU9wdGlvbnMoY29sb3JzID0gUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDMyLCAiU2V0MiIpKSAlPiUNCiAgICAgICAgICAgICAgICAgZHlIaWdobGlnaHQoaGlnaGxpZ2h0U2VyaWVzT3B0cyA9IGxpc3Qoc3Ryb2tlV2lkdGggPSAyKSkNCkcuVHJhYmFqbw0KYGBgDQoNCmBgYHtyLG91dC53aWR0aD0gIjEwMCUiLCBmaWcuYWxpZ249J2NlbnRlcicsZmlnLmNhcD0gIk1vdGl2bzogVHJhYmFqbyIsIGV2YWwgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkdyYWZpY29zL0dyYWZpY28gVHJhYmFqby5wbmciKQ0KYGBgDQoNCg0KIyMjIE1vdGl2byBkZSBlc3R1ZGlvICAgDQoNCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpHLkVzdHVkaW8gPC0gZHlncmFwaCh0cy5Fc3R1ZGlvLCBtYWluID0gIkVzdHVkaW8iLCB5bGFiID0gIk1pZ3JhbnRlcyIsIHhsYWIgPSAiUGVyaW9kbyIpICU+JQ0KICAgICAgICAgICAgICBkeVJhbmdlU2VsZWN0b3IoKSAlPiUNCiAgICAgICAgICAgICAgIGR5TGVnZW5kKHdpZHRoID0gNjUwKSAlPiUNCiAgICAgICAgICAgICAgICBkeU9wdGlvbnMoY29sb3JzID0gUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDMyLCAiU2V0MiIpKSAlPiUNCiAgICAgICAgICAgICAgICAgZHlIaWdobGlnaHQoaGlnaGxpZ2h0U2VyaWVzT3B0cyA9IGxpc3Qoc3Ryb2tlV2lkdGggPSAyKSkNCkcuRXN0dWRpbw0KYGBgDQoNCmBgYHtyLG91dC53aWR0aD0gIjEwMCUiLCBmaWcuYWxpZ249J2NlbnRlcicsZmlnLmNhcD0gIk1vdGl2bzogRXN0dWRpbyIsIGV2YWwgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkdyYWZpY29zL0dyYWZpY28gRXN0dWRpby5wbmciKQ0KYGBgDQoNCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIGVjaG8gPSBGQUxTRX0NCnRhYmxhIDwtIG15ZGF0YVssIGdyZXBsKCJFc3R1ZGlvIiwgbmFtZXMobXlkYXRhKSldDQoNCmthYmxlKGRlc2NyaWJlKHRhYmxhKSwNCiAgICAgIGRpZ2l0cyA9IDIsDQogICAgICBjYXB0aW9uID0gIkFuYWxpc2lzIGRlc2NyaXB0aXZvOiBFc3R1ZGlvIikgJT4lDQoga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsDQogICAgICAgICAgICAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIiwgImJvcmRlcmVkIiwgImhvdmVyIiksDQogICAgICAgICAgICAgICBmb250X3NpemUgPSA3LA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSAiY2VudGVyIiwNCiAgICAgICAgICAgICAgIGxhdGV4X29wdGlvbnM9ICJIT0xEX3Bvc2l0aW9uIikgJT4lIA0KICBnc3ViKCJmb250LXNpemU6IGluaXRpYWwgIWltcG9ydGFudDsiLCAiZm9udC1zaXplOiAxMHB0ICFpbXBvcnRhbnQ7IiwgLikgJT4lDQogICBnc3ViKCJ0ZXh0LWFsaWduOiBpbml0aWFsICFpbXBvcnRhbnQ7IiwgInRleHQtYWxpZ246IGp1c3RpZnkgIWltcG9ydGFudDsiLCAuKQ0KYGBgDQoNCiMjIyBNb3Rpdm8gc2UgdW5pw7MgbyBjYXPDsyAgICAgDQoNCg0KYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCkcuVW5pb24gPC0gZHlncmFwaCh0cy5VbmlvbiwgbWFpbiA9ICJTZSB1bmnDsyBvIGNhc8OzIiwgeWxhYiA9ICJNaWdyYW50ZXMiLCB4bGFiID0gIlBlcmlvZG8iKSAlPiUNCiAgICAgICAgICAgIGR5UmFuZ2VTZWxlY3RvcigpICU+JQ0KICAgICAgICAgICAgIGR5TGVnZW5kKHdpZHRoID0gNjUwKSAlPiUNCiAgICAgICAgICAgICAgZHlPcHRpb25zKGNvbG9ycyA9IFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCgzMiwgIlNldDIiKSkgJT4lDQogICAgICAgICAgICAgICBkeUhpZ2hsaWdodChoaWdobGlnaHRTZXJpZXNPcHRzID0gbGlzdChzdHJva2VXaWR0aCA9IDIpKQ0KRy5Vbmlvbg0KYGBgDQoNCmBgYHtyLG91dC53aWR0aD0gIjEwMCUiLCBmaWcuYWxpZ249J2NlbnRlcicsZmlnLmNhcD0gIk1vdGl2bzogU2UgdW5pw7MgbyBjYXPDsyIsIGV2YWwgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkdyYWZpY29zL0dyYWZpY28gVW5pb24ucG5nIikNCmBgYA0KDQoNCg0KYGBge3IsZmlnLmFsaWduPSdjZW50ZXInLCBlY2hvID0gRkFMU0V9DQp0YWJsYSA8LSBteWRhdGFbLCBncmVwbCgiVW5pb24iLCBuYW1lcyhteWRhdGEpKV0NCg0Ka2FibGUoZGVzY3JpYmUodGFibGEpLA0KICAgICAgZGlnaXRzID0gMiwNCiAgICAgIGNhcHRpb24gPSAiQW5hbGlzaXMgZGVzY3JpcHRpdm86IFNlIHVuacOzIG8gY2Fzw7MiKSAlPiUNCiBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwNCiAgICAgICAgICAgICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygiY29uZGVuc2VkIiwgInJlc3BvbnNpdmUiLCAiYm9yZGVyZWQiLCAiaG92ZXIiKSwNCiAgICAgICAgICAgICAgIGZvbnRfc2l6ZSA9IDcsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9ICJjZW50ZXIiLA0KICAgICAgICAgICAgICAgbGF0ZXhfb3B0aW9ucz0gIkhPTERfcG9zaXRpb24iKSAlPiUgDQogIGdzdWIoImZvbnQtc2l6ZTogaW5pdGlhbCAhaW1wb3J0YW50OyIsICJmb250LXNpemU6IDEwcHQgIWltcG9ydGFudDsiLCAuKSAlPiUNCiAgIGdzdWIoInRleHQtYWxpZ246IGluaXRpYWwgIWltcG9ydGFudDsiLCAidGV4dC1hbGlnbjoganVzdGlmeSAhaW1wb3J0YW50OyIsIC4pDQpgYGANCg0KDQojIyMgTW90aXZvIHNlIGRpY29yY2nDsyBvIHNlcGFyw7MgICANCg0KYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCkcuRGl2b3JjaW8gPC0gZHlncmFwaCh0cy5EaXZvcmNpbywgbWFpbiA9ICJTZSBkaWNvcmNpw7MgbyBzZXBhcsOzIiwgeWxhYiA9ICJNaWdyYW50ZXMiLCB4bGFiID0gIlBlcmlvZG8iKSAlPiUNCiAgICAgICAgICAgICAgIGR5UmFuZ2VTZWxlY3RvcigpICU+JQ0KICAgICAgICAgICAgICAgIGR5TGVnZW5kKHdpZHRoID0gNjUwKSAlPiUNCiAgICAgICAgICAgICAgICAgZHlPcHRpb25zKGNvbG9ycyA9IFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCgzMiwgIlNldDIiKSkgJT4lDQogICAgICAgICAgICAgICAgICBkeUhpZ2hsaWdodChoaWdobGlnaHRTZXJpZXNPcHRzID0gbGlzdChzdHJva2VXaWR0aCA9IDIpKQ0KRy5EaXZvcmNpbw0KYGBgDQoNCmBgYHtyLG91dC53aWR0aD0gIjEwMCUiLCBmaWcuYWxpZ249J2NlbnRlcicsZmlnLmNhcD0gIk1vdGl2bzogU2Ugc2VwYXLDsyBvIGRpdm9yY2nDsyIsIGV2YWwgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkdyYWZpY29zL0dyYWZpY28gRGl2b3JjaW8ucG5nIikNCmBgYA0KDQpgYGB7cixmaWcuYWxpZ249J2NlbnRlcicsIGVjaG8gPSBGQUxTRX0NCnRhYmxhIDwtIG15ZGF0YVssIGdyZXBsKCJEaXZvcmNpbyIsIG5hbWVzKG15ZGF0YSkpXQ0KDQprYWJsZShkZXNjcmliZSh0YWJsYSksDQogICAgICBkaWdpdHMgPSAyLA0KICAgICAgY2FwdGlvbiA9ICJBbmFsaXNpcyBkZXNjcmlwdGl2bzogU2Ugc2VwYXLDsyBvIGRpdm9yY2nDsyIpICU+JQ0KIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJjb25kZW5zZWQiLCAicmVzcG9uc2l2ZSIsICJib3JkZXJlZCIsICJob3ZlciIpLA0KICAgICAgICAgICAgICAgZm9udF9zaXplID0gNywNCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImNlbnRlciIsDQogICAgICAgICAgICAgICBsYXRleF9vcHRpb25zPSAiSE9MRF9wb3NpdGlvbiIpICU+JSANCiAgZ3N1YigiZm9udC1zaXplOiBpbml0aWFsICFpbXBvcnRhbnQ7IiwgImZvbnQtc2l6ZTogMTBwdCAhaW1wb3J0YW50OyIsIC4pICU+JQ0KICAgZ3N1YigidGV4dC1hbGlnbjogaW5pdGlhbCAhaW1wb3J0YW50OyIsICJ0ZXh0LWFsaWduOiBqdXN0aWZ5ICFpbXBvcnRhbnQ7IiwgLikNCmBgYA0KDQoNCiMjIyBNb3Rpdm8gcGFyYSByZXVuaXJzZSBjb24gdW4gZmFtaWxpYXIgIA0KIA0KYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCkcuRmFtaWxpYXIgPC0gZHlncmFwaCh0cy5GYW1pbGlhLCBtYWluID0gIlJldW5pcnNlIGNvbiB1biBmYW1pbGlhciIsIHlsYWIgPSAiTWlncmFudGVzIiwgeGxhYiA9ICJQZXJpb2RvIikgJT4lDQogICAgICAgICAgICAgICBkeVJhbmdlU2VsZWN0b3IoKSAlPiUNCiAgICAgICAgICAgICAgICBkeUxlZ2VuZCh3aWR0aCA9IDY1MCkgJT4lDQogICAgICAgICAgICAgICAgIGR5T3B0aW9ucyhjb2xvcnMgPSBSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwoMzIsICJTZXQyIikpICU+JQ0KICAgICAgICAgICAgICAgICAgZHlIaWdobGlnaHQoaGlnaGxpZ2h0U2VyaWVzT3B0cyA9IGxpc3Qoc3Ryb2tlV2lkdGggPSAyKSkNCkcuRmFtaWxpYXINCmBgYA0KDQpgYGB7cixvdXQud2lkdGg9ICIxMDAlIiwgZmlnLmFsaWduPSdjZW50ZXInLGZpZy5jYXA9ICJNb3Rpdm86IFJldW5pcnNlIGNvbiB1biBmYW1pbGlhciIsIGV2YWwgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkdyYWZpY29zL0dyYWZpY28gRmFtaWxpYXIucG5nIikNCmBgYA0KDQpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBlY2hvID0gRkFMU0V9DQp0YWJsYSA8LSBteWRhdGFbLCBncmVwbCgiRmFtaWxpYXIiLCBuYW1lcyhteWRhdGEpKV0NCg0Ka2FibGUoZGVzY3JpYmUodGFibGEpLA0KICAgICAgZGlnaXRzID0gMiwNCiAgICAgIGNhcHRpb24gPSAiQW5hbGlzaXMgZGVzY3JpcHRpdm86IFJldW5pcnNlIGNvbiB1biBmYW1pbGlhciIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwNCiAgICAgICAgICAgICAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiKSwNCiAgICAgICAgICAgICAgICBmb250X3NpemUgPSA3LA0KICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImNlbnRlciIsDQogICAgICAgICAgICAgICAgbGF0ZXhfb3B0aW9ucz0gIkhPTERfcG9zaXRpb24iKQ0KYGBgDQoNCmBgYHtyLGV2YWw9RkFMU0UsIGVjaG8gPSBGQUxTRX0NCiNodHRwczovL2dpdGh1Yi5jb20vcnN0dWRpby9keWdyYXBocy9pc3N1ZXMvNzENCnNhdmVXaWRnZXQoRy5UcmFiYWpvLCAiR3JhZmljbyBUcmFiYWpvLmh0bWwiLCBzZWxmY29udGFpbmVkID0gVFJVRSwgbGliZGlyID0gTlVMTCkNCnNhdmVXaWRnZXQoRy5Fc3R1ZGlvLCAiR3JhZmljbyBFc3R1ZGlvLmh0bWwiLCBzZWxmY29udGFpbmVkID0gVFJVRSwgbGliZGlyID0gTlVMTCkNCnNhdmVXaWRnZXQoRy5VbmlvbiwgIkdyYWZpY28gVW5pb24uaHRtbCIsIHNlbGZjb250YWluZWQgPSBUUlVFLCBsaWJkaXIgPSBOVUxMKQ0Kc2F2ZVdpZGdldChHLkRpdm9yY2lvLCAiR3JhZmljbyBEaXZvcmNpby5odG1sIiwgc2VsZmNvbnRhaW5lZCA9IFRSVUUsIGxpYmRpciA9IE5VTEwpDQpzYXZlV2lkZ2V0KEcuRmFtaWxpYXIsICJHcmFmaWNvIEZhbWlsaWFyLmh0bWwiLCBzZWxmY29udGFpbmVkID0gVFJVRSwgbGliZGlyID0gTlVMTCkNCg0Kd2lkdGg8LSAxMDgwDQpoZWlnaHQgPC0gNjEwDQojU2UgY29udmllcnRlbiBkZSBodG1sIGEgLnBkZg0Kd2Vic2hvdCh1cmwgPSAiR3JhZmljbyBUcmFiYWpvLmh0bWwiLCBmaWxlID0gIkdyYWZpY28gVHJhYmFqby5wbmciLA0KICAgICAgICBjbGlwcmVjdCA9IGMoMTAsIDMwLCB3aWR0aCArIDUwLCBoZWlnaHQgKyA1MCksDQogICAgICAgIHZ3aWR0aCA9IHdpZHRoLCANCiAgICAgICAgdmhlaWdodCA9IGhlaWdodCkNCndlYnNob3QodXJsID0gIkdyYWZpY28gRXN0dWRpby5odG1sIiwgZmlsZSA9ICJHcmFmaWNvIEVzdHVkaW8ucG5nIiwNCiAgICAgICAgY2xpcHJlY3QgPSBjKDEwLCAzMCwgd2lkdGggKyA1MCwgaGVpZ2h0ICsgNTApLA0KICAgICAgICB2d2lkdGggPSB3aWR0aCwgDQogICAgICAgIHZoZWlnaHQgPSBoZWlnaHQpDQp3ZWJzaG90KHVybCA9ICJHcmFmaWNvIFVuaW9uLmh0bWwiLCBmaWxlID0gIkdyYWZpY28gVW5pb24ucG5nIiwNCiAgICAgICAgY2xpcHJlY3QgPSBjKDEwLCAzMCwgd2lkdGggKyA1MCwgaGVpZ2h0ICsgNTApLA0KICAgICAgICB2d2lkdGggPSB3aWR0aCwgDQogICAgICAgIHZoZWlnaHQgPSBoZWlnaHQpDQp3ZWJzaG90KHVybCA9ICJHcmFmaWNvIERpdm9yY2lvLmh0bWwiLCBmaWxlID0gIkdyYWZpY28gRGl2b3JjaW8ucG5nIiwNCiAgICAgICAgY2xpcHJlY3QgPSBjKDEwLCAzMCwgd2lkdGggKyA1MCwgaGVpZ2h0ICsgNTApLA0KICAgICAgICB2d2lkdGggPSB3aWR0aCwgDQogICAgICAgIHZoZWlnaHQgPSBoZWlnaHQpDQp3ZWJzaG90KHVybCA9ICJHcmFmaWNvIEZhbWlsaWFyLmh0bWwiLGZpbGUgPSAiR3JhZmljbyBGYW1pbGlhci5wbmciLA0KICAgICAgICBjbGlwcmVjdCA9IGMoMTAsIDMwLCB3aWR0aCArIDUwLCBoZWlnaHQgKyA1MCksDQogICAgICAgIHZ3aWR0aCA9IHdpZHRoLCANCiAgICAgICAgdmhlaWdodCA9IGhlaWdodCkNCmBgYCANCg0KIyMgTW9kZWxvIGplcsOhcnF1aWNvDQoNClNlIHV0aWxpemEgbGEgZnVuY2nDs24gYGh0cygpYCBwYXJhIGNyZWFyIHVuYSBzZXJpZSBkZSB0aWVtcG8gamVyw6FycXVpY2EuIA0KDQpEb25kZSBzZSB1dGlsaXphbiBsb3MgZGF0b3MgZGUgw7psdGltbyBuaXZlbCB5IHNlIHV0aWxpemEgZWwgYXJndW1lbnRvIGBjaGFyYWN0ZXJzYCBkb25kZSBsb3MgcHJpbWVyb3MgZG9zIGNhcmFjdGVyZXMgY29ycmVzcG9uZGVuIGFsIHByaW1lciBuaXZlbCAoUmVnacOzbiksIGxvcyBzaWd1aWVudGVzIGRvcyBjb3JyZXNwb25kZW4gYWwgc2VndW5kbyBuaXZlbCAoQ2l1ZGFkZXMpIHkgY29tbyDDumx0aW1vIGxvcyB0cmVzIGNhcmFjdGVyZXMgY29ycmVzcG9uZGVuIGFsIG1vdGl2byBkZSBsYSBhdXNlbmNpYS4gICANCg0KLSBgVFJBYCA9ICJUcmFiYWpvIiAgIA0KLSBgRVNUYCA9ICJFc3R1ZGlvIiAgIA0KLSBgVU5JYCA9ICJTZSBjYXPDsyBvIHVuacOzIiAgIA0KLSBgRElWYCA9ICJTZSBkaXZvcmNpw7MgbyBzZXBhcsOzIiAgICANCi0gYEZBTWAgPSAiUmV1bmlyc2UgY29uIHVuIGZhbWlsaWFyIiAgIA0KDQoqKkRlZmluaWNpw7NuIGRlIHZlY3RvcmVzOioqICAgDQoNCi0gYFJlZ2lvbmVzYDogVW4gdmVjdG9yIHF1ZSBjb250aWVuZSBjw7NkaWdvcyBkZSByZWdpb25lcyByZXBldGlkb3MgcGFyYSBjcmVhciB1bmEgZXRpcXVldGEgZGUgcmVnacOzbiBlc3BlY8OtZmljYS4NCi0gYENpdWRhZGVzYDogVW4gdmVjdG9yIHF1ZSBjb250aWVuZSBjw7NkaWdvcyBkZSBjaXVkYWRlcyBxdWUgc2UgY29tYmluYW4gY29uIGxhcyByZWdpb25lcyBwYXJhIGNyZWFyIG5vbWJyZXMgw7puaWNvcy4NCi0gYE1vdGl2b2A6IFVuIHZlY3RvciBxdWUgY29udGllbmUgZWwgbW90aXZvIGRlIGxhIGF1c2VuY2lhLCByZXBldGlkbyBwYXJhIGlndWFsYXIgbGEgbG9uZ2l0dWQgZGUgbG9zIG90cm9zIHZlY3RvcmVzLiAgIA0KDQpgYGB7cixlY2hvID0gVFJVRX0NClJlZ2lvbmVzIDwtIHJlcChjKHJlcCgiQ0UiLCA3KSwNCiAgICAgICAgICAgICAgICAgIHJlcCgiTkUiLCA1KSwNCiAgICAgICAgICAgICAgICAgIHJlcCgiTlciLCA1KSwNCiAgICAgICAgICAgICAgICAgIHJlcCgiV0UiLCA4KSwNCiAgICAgICAgICAgICAgICAgIHJlcCgiU08iLCA3KSksIDUpDQpDaXVkYWRlcyA8LSByZXAoYygiMTEiLCAJIjI0IiwgCSIwMSIsIAkiMzIiLCAJIjA0IiwgCSIxNCIsIAkiMjkiLA0KICAgICAgICAgICAgICAgICAgIjIxIiwgCSIwMyIsIAkiMDYiLCAJIjE1IiwgCSIwOSIsDQogICAgICAgICAgICAgICAgICAiMDgiLCAJIjE5IiwgCSIyMCIsIAkiMzAiLCAJIjE4IiwgCQ0KICAgICAgICAgICAgICAgICAgIjEyIiwgCSIyNyIsIAkiMDIiLCAJIjA1IiwgCSIxMyIsIAkiMjgiLCAJIjIyIiwgCSIyNiIsIAkNCiAgICAgICAgICAgICAgICAgICIzMSIsIAkiMjMiLCAJIjA3IiwgCSIyNSIsIAkiMTciLCAJIjEwIiwgCSIxNiIpLCA1KQ0KDQpNb3Rpdm8gPC0gYyhyZXAoIlRSQSIsIDMyKSwNCiAgICAgICAgICAgIHJlcCgiRVNUIiwgMzIpLA0KICAgICAgICAgICAgcmVwKCJVTkkiLCAzMiksDQogICAgICAgICAgICByZXAoIkRJViIsIDMyKSwNCiAgICAgICAgICAgIHJlcCgiRkFNIiwgMzIpKQ0KDQpub21icmVzIDwtIHBhc3RlMChSZWdpb25lcywgQ2l1ZGFkZXMsIE1vdGl2bykgI0xhcmdvIGRlIDcgfCBSZWdpb25lcz0yfENpdWRhZGVzPTJ8TW90aXZvPTMNCmNvbG5hbWVzKHRzLm15ZGF0YSkgPC0gbm9tYnJlcw0KDQpub2RlcyA8LSBsaXN0KDE2MCwgYyg1LCAzMiwgNSkpICMxNjAgdmFyaWFibGVzIHxSZWdpb25lcz01fENpdWRhZGVzPTMyfE1vdGl2b3M9NXwgIA0KTW9kZWxvMiA8LSBodHModHMubXlkYXRhLCBub2RlcyA9IG5vZGVzLGNoYXJhY3RlcnMgPSBjKDIsIDIsIDMpKQ0KDQojQ2FtYmlhbW9zIGxvcyBsYWJlbHMgDQpNb2RlbG8yJGxhYmVscyRgTGV2ZWwgMWAgPC0gYygiQ2VudHJvIiwgIk5vcmVzdGUiLCAiTm9yb2VzdGUiLCAiU3VyZXN0ZSIsICJPY2NpZGVudGUiKQ0KYGBgDQoNCiMjIyBOaXZlbCAxOiBSZWdpw7NuICAgDQoNClNlIHZpc3VhbGl6YW4gbGFzIHNlcmllcyB0ZW1wb3JhbGVzIGFncmVnYWRhcyBkZSB1biBtb2RlbG8gamVyw6FycXVpY28gZGUgc2VyaWVzIHRlbXBvcmFsZXMgKGBNb2RlbG8xYCkuICAgDQoNCi0gYGFnZ3RzKGxldmVsID0gMSlgOiBFeHRyYWUgbGFzIHNlcmllcyB0ZW1wb3JhbGVzIGFncmVnYWRhcyBkZWwgbml2ZWwgMSBkZWwgbW9kZWxvIE1vZGVsbzEuIEVsIGBsZXZlbCA9IDEgYGluZGljYSBxdWUgc2UgZXN0w6EgZXh0cmF5ZW5kbyBkYXRvcyBkZWwgbml2ZWwgbcOhcyBhbHRvIGVuIGxhIGplcmFycXXDrWEuICAgICAgIA0KDQpgYGB7cn0NCk1vZGVsbzIgJT4lIA0KIGFnZ3RzKGxldmVsID0gMSkgJT4lDQogIGF1dG9wbG90KHNpemUgPSAxKSArIA0KICAgdGhlbWVfY2xhc3NpYygpICsgDQogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksDQogICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjIsICJjbSIpKSArDQogICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZCgpICsgDQogICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDUsICJEYXJrMiIpKSArIA0KICAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNSwgMjAxOSwgYnkgPSAyKSkgKw0KICAgICAgICBsYWJzKHRpdGxlID0gIk1vdGl2byBkZSBsYSBhdXNlbmNpYSAyMDA1LTIwMTkiLA0KICAgICAgICAgICAgIHN1YnRpdGxlID0gIlRyYWJham8gLyBFc3R1ZGlvIC8gU2UgY2Fzw7MgbyB1bmnDsyAvIERpdm9yY2nDsyBvIHNlcGFyw7MgLyBSZXVuaXJzZSBjb24gdW4gZmFtaWxpYXIiLA0KICAgICAgICAgICAgIHkgPSAiUmF0ZSIsDQogICAgICAgICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICAgICAgICBjb2xvciA9ICJTZXJpZXMiKSANCmBgYA0KDQojIyBOaXZlbCAyOiBDdWlkYWQgYXV0b3JlcHJlc2VudGFkYSAgICANCg0KQSBjb250aW51YWNpw7NuIHNlIG11ZXRyYW4gbG9zIGRhdG9zIGRlc2dsb3NhZG9zIHBvciBsYXMgMzIgY2l1ZGFkZXMuIA0KDQotIGBhZ2d0cyhsZXZlbCA9IDIpYDogaW5kaWNhIHF1ZSBzZSBlc3TDoW4gZXh0cmF5ZW5kbyBkYXRvcyBkZSB1biBuaXZlbCBkZSBqZXJhcnF1w61hIGluZmVyaW9yIGFsIG5pdmVsIDEuICANCg0KYGBge3J9DQpNb2RlbG8yICU+JSANCiBhZ2d0cyhsZXZlbCA9IDIpICU+JQ0KICBhdXRvcGxvdChzaXplID0gMC41KSArIA0KICAgdGhlbWVfY2xhc3NpYygpICsgDQogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksDQogICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICJsaW5lcyIpLA0KICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArDQogICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwoOCwgIkRhcmsyIikpKDYwKSkgKyANCiAgICAgIGd1aWRlcyhjb2wgPSBndWlkZV9sZWdlbmQobmNvbCA9IDE1KSkrDQogICAgICAgbGFicyh0aXRsZSA9ICJNb3Rpdm8gZGUgbGEgYXVzZW5jaWEgMjAwNS0yMDE5IiwNCiAgICAgICAgICAgIHN1YnRpdGxlID0gIlRyYWJham8gLyBFc3R1ZGlvIC8gU2UgY2Fzw7MgbyB1bmnDsyAvIERpdm9yY2nDsyBvIHNlcGFyw7MgLyBSZXVuaXJzZSBjb24gdW4gZmFtaWxpYXIiLA0KICAgICAgICAgICAgeSA9ICJSYXRlIiwNCiAgICAgICAgICAgIHggPSAiWWVhciIsDQogICAgICAgICAgICBjb2xvciA9ICJTZXJpZXMiKSANCmBgYA0KDQpTaSBiaWVuIGxhIGdyw6FmaWNhIGFudGVyaW9yIG5vIHBlcm1pdGUgc3UgaW50ZXJwcmV0YWJpbGlkYWQgZGViaWRvIGEgcXVlIHRvZG8gZWwgZW5zYW1ibGUgZGUgbGFzIHNlcmllcyBlc3TDoW4gbXV5IGp1bnRhcy4gDQoNCkhhY2llbmRvIHVzbyBkZSBsYSBmdW5jacOzbiBgYWdndHNgIGV4dHJhZSBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgZGUgdW4gb2JqZXRvIGBodHNgIHBhcmEgY3VhbHF1aWVyIG5pdmVsIGRlIGRlc2FncmVnYWNpw7NuLiBQYXJhIGBhZ2d0cyhNb2RlbG8xLCBsZXZlbCA9IDIpYCwgc2UgZXNwZWNpZmljYSBxdWUgcXVlcmVtb3MgZXh0cmFlciBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgZGVsIG5pdmVsIDIgZGVsIG1vZGVsbyBqZXLDoXJxdWljby4gTG9zIG5pdmVsZXMgZW4gdW4gbW9kZWxvIGplcsOhcnF1aWNvIGNvcnJlc3BvbmRlbiBhIGRpZmVyZW50ZXMgbml2ZWxlcyBkZSBhZ3JlZ2FjacOzbiBlbiBsYSBqZXJhcnF1w61hIGRlIGRhdG9zLiANCg0KUGFyYSBlc3RlIGNhc28sIHNlIGVzdMOhbiB0cmFiYWphbmRvIGNvbiBkb3Mgbml2ZWxlcyBkZSBkZXNhZ3JlZ2FjacOzbiAoUmVnaW9uZXMgeSBDaXVkYWRlcykgeSBiaWVuIHVuIE5pdmVsIENlcm8gKFRvdGFsKS4gICANCg0KYGBge3IsZWNobyA9IFRSVUV9DQpncm91cHMgPC0gYWdndHMoTW9kZWxvMiwgbGV2ZWwgPSAyKQ0KYGBgDQoNCmBgYHtyLGZpZy53aWR0aCA9IDEwLGZpZy5oZWlnaHQgPSAxMn0NCnRpYmJsZTo6YXNfdGliYmxlKGdyb3VwcykgJT4lDQogdGlkeXI6OmdhdGhlcihTZXJpZXMpICU+JQ0KICBtdXRhdGUoRGF0ZSA9IHJlcCh0aW1lKGdyb3VwcyksIE5DT0woZ3JvdXBzKSksDQogICAgICAgICBHcm91cCA9c3RyaW5ncjo6c3RyX2V4dHJhY3QoU2VyaWVzLCAiKFtBLVphLXogXSopIikpICU+JQ0KICAgZ2dwbG90KGFlcyh4ID0gRGF0ZSwgeSA9IHZhbHVlLCBncm91cCA9IFNlcmllcywgY29sb3VyID0gU2VyaWVzKSkgKw0KICAgIGdlb21fbGluZSgpICsgDQogICAgIHRoZW1lX2NsYXNzaWMoKSArDQogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpLA0KICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLA0KICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICJsaW5lcyIpLA0KICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsNCiAgICAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2QoKSArDQogICAgICAgI3NjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwoOCwgIkRhcmsyIikpKDMzKSkgKyANCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxOTgwLCAyMDE1LCBieSA9IDUpKSArDQogICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkgKw0KICAgICAgICAgIGd1aWRlcyhjb2wgPSBndWlkZV9sZWdlbmQobmNvbCA9IDE1KSkrDQogICAgICAgICAgIGxhYnModGl0bGUgPSAiTW90aXZvIGRlIGxhIGF1c2VuY2lhIDIwMDUtMjAxOSIsDQogICAgICAgICAgICAgICAgc3VidGl0bGUgPSAiVHJhYmFqbyAvIEVzdHVkaW8gLyBTZSBjYXPDsyBvIHVuacOzIC8gRGl2b3JjacOzIG8gc2VwYXLDsyAvIFJldW5pcnNlIGNvbiB1biBmYW1pbGlhciIsDQogICAgICAgICAgICAgICAgeSA9ICJSYXRlIiwNCiAgICAgICAgICAgICAgICB4ID0gIlllYXIiLA0KICAgICAgICAgICAgICAgIGNvbG9yID0gIlNlcmllcyIpICsNCiAgICAgICAgICAgIGZhY2V0X3dyYXAoLiB+IEdyb3VwKSANCmBgYA0KDQojIyBOaXZlbCAzOiBNb3Rpdm8gZGUgbGEgYXVzZW5jaWEgICAgDQoNCkhhY2llbmRvIHVzbyBkZSBsYSBmdW5jacOzbiBgYWdndHNgIGV4dHJhZSBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgZGUgdW4gb2JqZXRvIGBodHNgIHBhcmEgY3VhbHF1aWVyIG5pdmVsIGRlIGRlc2FncmVnYWNpw7NuLiBQYXJhIGBhZ2d0cyhNb2RlbG8yLCBsZXZlbCA9IDMpYCwgc2UgZXNwZWNpZmljYSBxdWUgcXVlcmVtb3MgZXh0cmFlciBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgZGVsIG5pdmVsIDIzIGRlbCBtb2RlbG8gamVyw6FycXVpY28uIExvcyBuaXZlbGVzIGVuIHVuIG1vZGVsbyBqZXLDoXJxdWljbyBjb3JyZXNwb25kZW4gYSBkaWZlcmVudGVzIG5pdmVsZXMgZGUgYWdyZWdhY2nDs24gZW4gbGEgamVyYXJxdcOtYSBkZSBkYXRvcy4gDQoNCkVuIG1vZGVsbyBnZW5lcmFsLCBzZSBlc3TDoW4gdHJhYmFqYW5kbyBjb24gdHJlcyBuaXZlbGVzIGRlIGRlc2FncmVnYWNpw7NuIChgTW90aXZvIGRlIGF1c2VuY2lhYCwgYFJlZ2lvbmVzYCB5IGBDaXVkYWRlc2ApIHkgYmllbiB1biBOaXZlbCBDZXJvIChgVG90YWxgKS4gICAgDQoNCmBgYHtyLGVjaG8gPSBUUlVFfQ0KZ3JvdXBzIDwtIGFnZ3RzKE1vZGVsbzIsIGxldmVsID0gMykNCmBgYA0KDQpgYGB7cixmaWcud2lkdGggPSAxMCxmaWcuaGVpZ2h0ID0gMTJ9DQojaHR0cHM6Ly9zdHJpbmdyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL3N0cl9sb2NhdGUuaHRtbA0KdGliYmxlOjphc190aWJibGUoZ3JvdXBzKSAlPiUNCiB0aWR5cjo6Z2F0aGVyKFNlcmllcykgJT4lIA0KICBtdXRhdGUoRGF0ZSA9IHJlcCh0aW1lKGdyb3VwcyksIE5DT0woZ3JvdXBzKSksDQogICAgICAgICBHcm91cCA9c3RyaW5ncjo6c3RyX2V4dHJhY3QoU2VyaWVzLCAiKFtBLVphLXogXSopIiksDQogICAgICAgICBNb3Rpdm89c3RyaW5ncjo6c3RyX3N1YihTZXJpZXMsNSwgNykpICU+JQ0KICAgZ2dwbG90KGFlcyh4ID0gRGF0ZSwgeSA9IHZhbHVlLCBncm91cCA9IFNlcmllcywgY29sb3VyID0gU2VyaWVzKSkgKw0KICAgIGdlb21fbGluZSgpICsgDQogICAgIHRoZW1lX2NsYXNzaWMoKSArDQogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpLA0KICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLA0KICAgICAgICAgICAgbGVnZW5kLmtleS53aWR0aD11bml0KDAuMiwgImNtIiksDQogICAgICAgICAgICBsZWdlbmQua2V5LmhlaWdodCA9IHVuaXQoMCwgImNtIiksDQogICAgICAgICAgICBsZWdlbmQuc3BhY2luZy54ID0gdW5pdCgwLCAiY20iKSwNCiAgICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAibGluZXMiKSwNCiAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArDQogICAgICAgc2NhbGVfY29sb3JfdmlyaWRpc19kKCkgKw0KICAgICAgICNzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDgsICJEYXJrMiIpKSgxNjApKSArIA0KICAgICAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDE5ODAsIDIwMTUsIGJ5ID0gNSkpICsNCiAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKSArDQogICAgICAgICAgZ3VpZGVzKGNvbCA9IGd1aWRlX2xlZ2VuZChuY29sID0gMTUpKSsNCiAgICAgICAgICAgbGFicyh0aXRsZSA9ICJNb3Rpdm8gZGUgbGEgYXVzZW5jaWEgMjAwNS0yMDE5IiwNCiAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9ICJUcmFiYWpvIC8gRXN0dWRpbyAvIFNlIGNhc8OzIG8gdW5pw7MgLyBEaXZvcmNpw7MgbyBzZXBhcsOzIC8gUmV1bmlyc2UgY29uIHVuIGZhbWlsaWFyIiwNCiAgICAgICAgICAgICAgICB5ID0gIlJhdGUiLA0KICAgICAgICAgICAgICAgIHggPSAiWWVhciIsDQogICAgICAgICAgICAgICAgY29sb3IgPSAiU2VyaWVzIikgKw0KICAgICAgICAgICAgZmFjZXRfd3JhcCguIH4gR3JvdXAgKyBNb3Rpdm8pIA0KYGBgDQoNCkFuYWxpemFuZG8gbGEgZ3LDoWZpY2EgYW50ZXJpb3IgZWwgbW90aXZvIGRlIGF1c2VuY2lhIHBhcmEgIlJldW5pcnNlIGNvbiB1biBmYW1pbGlhciIgZXMgbGEgcXVlIHByZXNlbnRhIHVuIG1heW9yIG7Dum1lcm8gZGUgY2Fzb3MgbWlncmF0b3Jpb3MiIGNvbiByZXNwZWN0byBhIGxvcyBvdHJvcyBjdWF0cm8gY2Fzb3MuICAgICAgDQoNCmBgYHtyfQ0KI3ByaW50KE1vZGVsbzIpDQojc21hdHJpeChNb2RlbG8yKQ0KI2FsbHRzKE1vZGVsbzIpDQpgYGANCg0KIyMgRm9yZWNhc3Rpbmc6IE1vdGl2byBkZSBsYSBhdXNlbmNpYSBlbiBnZW5lcmFsICAgDQoNClNlIHJlYWxpemEgdW4gcHJvbsOzc3RpY28gamVyw6FycXVpY28gc29icmUgYE1vZGVsbzJgIHBhcmEgbG9zIHByw7N4aW1vcyAxMCBwZXJpb2RvcywgdXRpbGl6YW5kbyBlbCBtw6l0b2RvIGRlIGAibWlkZGxlLW91dCJgIHBhcmEgbGEgYWdyZWdhY2nDs24gamVyw6FycXVpY2EgeSBlbCBtb2RlbG8gYEFSSU1BYCBwYXJhIGxvcyBwcm9uw7NzdGljb3MgaW5kaXZpZHVhbGVzLiAgIA0KDQpTZSBlc3BlcmEgcXVlIGxvcyBwcm9uw7NzdGljb3Mgc2VhbiBjb25zaXN0ZW50ZXMgY29uIGxhIGVzdHJ1Y3R1cmEgZGUgYWdyZWdhY2nDs24gZGUgbGFzIHNlcmllcyBkZSAgdGllbXBvIGFsIGFncnVwYXJsYXMuICAgIA0KDQpgYGB7ciwgZWNobyA9IFRSVUV9DQojaD1mb3Jlc2Nhc3QgaG9yaXpvbg0KI21ldGhvZDwtIm1vIiwgImJ1IiwgInRkZnAiDQpmLm1vZGVsbzIgPC0gZm9yZWNhc3QoTW9kZWxvMiwgaCA9IDEwLCBtZXRob2QgPSAibW8iLCBsZXZlbCA9IDIsIGZtZXRob2QgPSAiYXJpbWEiLCBwYXJhbGxlbCA9IFRSVUUsIGtlZXAuZml0dGVkID0gVFJVRSkNCmBgYA0KDQpgYGB7cixlY2hvID0gVFJVRSwgZXZhbCA9IEZBTFNFfQ0Kc3VtbWFyeShmLm1vZGVsbzIpDQpgYGANCg0KIyMjIE5pdmVsIDAgYWwgMjogVG90YWwgLyBSZWdpw7NuIC8gQ2l1ZGFkICAgDQoNClNlIGV4dHJhZW4gbGFzIHNlcmllcyB0ZW1wb3JhbGVzIHBhcmEgbG9zIG5pdmVsZXMgMCwgMSB5IDIgdGFudG8gZGVsIG1vZGVsbyBkZSBwcm9uw7NzdGljbyAoYGZjc3QyYCkgY29tbyBkZWwgbW9kZWxvIG9yaWdpbmFsIChgZ3JvdXBzYCkuIEVzdG8gdGUgcGVybWl0aXLDoSBjb21wYXJhciBsb3MgZGF0b3Mgb3JpZ2luYWxlcyBjb24gbG9zIHByb27Ds3N0aWNvcyBnZW5lcmFkb3MgYSBkaWZlcmVudGVzIG5pdmVsZXMgZGUgbGEgamVyYXJxdcOtYS4gICAgIA0KLSBgbGV2ZWxzID0gMDoyYDogRXNwZWNpZmljYSBxdWUgc2UgZGViZW4gZXh0cmFlciBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgcGFyYSBsb3Mgbml2ZWxlcyAwLCAxIHkgMiBkZWwgbW9kZWxvIGplcsOhcnF1aWNvLiAgDQoNCmBgYHtyLGVjaG8gPSBUUlVFfQ0KZmNzdDIgPC0gYWdndHMoZi5tb2RlbG8yLCBsZXZlbHMgPSAwOjIpDQpncm91cHMgPC0gYWdndHMoTW9kZWxvMiwgbGV2ZWxzID0gMDoyKQ0KYGBgDQoNCmBgYHtyLGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gOH0NCmF1dG9wbG90KGZjc3QyLCBzaXplID0gMC41KSArDQogYXV0b2xheWVyKGdyb3VwcykgKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAyMDE5LGNvbG9yID0gIiNBOEFCRDciLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogICB0aGVtZV9jbGFzc2ljKCkgKw0KICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpLA0KICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAibGluZXMiKSwNCiAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKw0KICAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2QoKSArIA0KICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA1LCAyMDI1LCBieSA9IDIpKSArDQogICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpICsNCiAgICAgICAgZ3VpZGVzKGNvbCA9IGd1aWRlX2xlZ2VuZChuY29sID0gMTUpKSsNCiAgICAgICAgIGxhYnModGl0bGUgPSAiTW90aXZvIGRlIGxhIGF1c2VuY2lhIDIwMDUtMjAxOSIsDQogICAgICAgICAgICAgIHN1YnRpdGxlID0gIlRyYWJham8gLyBFc3R1ZGlvIC8gU2UgY2Fzw7MgbyB1bmnDsyAvIERpdm9yY2nDsyBvIHNlcGFyw7MgLyBSZXVuaXJzZSBjb24gdW4gZmFtaWxpYXIiLA0KICAgICAgICAgICAgICB5ID0gIlJhdGUiLA0KICAgICAgICAgICAgICB4ID0gIlllYXIiLA0KICAgICAgICAgICAgICBjb2xvciA9ICJTZXJpZXMiKSANCmBgYA0KDQpTZSBjcmVhIHVuYSBzZXJpZSB0ZW1wb3JhbCBjb21iaW5hZGEgZGUgbGFzIHNlcmllcyB0ZW1wb3JhbGVzIG9yaWdpbmFsZXMgeSBsb3MgcHJvbsOzc3RpY29zLiAgIA0KDQpgYGB7cixlY2hvID0gVFJVRX0NCnRhYmxhIDwtIHRzKHJiaW5kKGdyb3VwcywgZmNzdDIpLA0KICAgICAgICAgICAgICAgICAgc3RhcnQgPSBzdGFydChncm91cHMpLCBmcmVxdWVuY3kgPSA0KSAjRnJlY3VlbmNpYSBhbCBhw7FvDQpgYGANCg0KIyMjIE5pdmVsIDA6IFRvdGFsIGRlIGNhc29zIGRlIG1pZ3JhY2nDs24gICANCg0KQSBjb250aW51YWNpw7NuIHNlIG11ZXRyYW4gbG9zIGRhdG9zIGRlc2dsb3NhZG9zIGEgbml2ZWwgTmFjaW9uYWwuICANCg0KYGBge3J9DQojaHR0cDovL3d3dy5zdGhkYS5jb20vZW5nbGlzaC93aWtpL2dncGxvdDItbGluZS10eXBlcy1ob3ctdG8tY2hhbmdlLWxpbmUtdHlwZXMtb2YtYS1ncmFwaC1pbi1yLXNvZnR3YXJlDQphdXRvcGxvdCh0YWJsYVssICJUb3RhbCJdLCBjb2xvdXIgPSAiIzE3MjBCNyIsIHNpemUgPSAxLjIsIGFscGhhID0gMC42LCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArICAgICAgDQogZ2VvbV92bGluZSh4aW50ZXJjZXB0PTIwMTkuNSxjb2xvciA9ICIjQThBQkQ3IixsaW5ldHlwZT0gImRhc2hlZCIpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSkgKyANCiAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA1LCAyMDI1LCBieSA9IDIpKSArDQogICAgIGxhYnModGl0bGUgPSAiTW90aXZvIGRlIGxhIGF1c2VuY2lhIDIwMDUtMjAxOSIsDQogICAgICAgICAgc3VidGl0bGUgPSAiVHJhYmFqbyAvIEVzdHVkaW8gLyBTZSBjYXPDsyBvIHVuacOzIC8gRGl2b3JjacOzIG8gc2VwYXLDsyAvIFJldW5pcnNlIGNvbiB1biBmYW1pbGlhciIsDQogICAgICAgICAgeSA9ICJSYXRlIiwNCiAgICAgICAgICB4ID0gIlllYXIiLA0KICAgICAgICAgIGNvbG9yID0gIlNlcmllcyIpIA0KYGBgDQoNCiMjIyBOaXZlbCAxIGEgMjogTml2ZWwgcmVnacOzbiB5IG5pdmVsIGNpdWRhZCAgDQoNCkEgY29udGludWFjacOzbiBzZSBtdWV0cmFuIGxvcyBkYXRvcyBkZXNnbG9zYWRvcyBhIG5pdmVsIFJlZ2nDs24uICANCg0KYGBge3IsZmlnLndpZHRoID0gMTAsZmlnLmhlaWdodCA9IDV9DQphc190aWJibGUodGFibGFbLC0xXSkgJT4lDQogdGlkeXI6OmdhdGhlcihTZXJpZXMpICU+JQ0KICBtdXRhdGUoRGF0ZSA9IHJlcCh0aW1lKHRhYmxhKSwgTkNPTCh0YWJsYSktMSksDQogICAgICAgICBHcm91cCA9IHN0cl9leHRyYWN0KFNlcmllcywgIihbQS1aYS16IF0qKSIpKSAlPiUNCiAgIGdncGxvdChhZXMoeCA9IERhdGUsIHkgPSB2YWx1ZSwgZ3JvdXAgPSBTZXJpZXMsIGNvbG91ciA9IFNlcmllcykpICsNCiAgICBnZW9tX2xpbmUoKSArDQogICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDIwMTksY29sb3IgPSAiI0E4QUJENyIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIA0KICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSwNCiAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksDQogICAgICAgICAgICAgbGVnZW5kLmtleS53aWR0aCA9IHVuaXQoMC4yLCAiY20iKSwNCiAgICAgICAgICAgICBsZWdlbmQua2V5LmhlaWdodCA9IHVuaXQoMCwgImNtIiksDQogICAgICAgICAgICAgbGVnZW5kLnNwYWNpbmcueCA9IHVuaXQoMC4xLCAiY20iKSwNCiAgICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuNSwgImxpbmVzIiksDQogICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsNCiAgICAgICAgc2NhbGVfY29sb3JfdmlyaWRpc19kKCkgKw0KICAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA1LCAyMDI1LGJ5ID0gNSkpICsNCiAgICAgICAgICBndWlkZXMoY29sID0gZ3VpZGVfbGVnZW5kKG5jb2wgPSAxNSkpICsNCiAgICAgICAgICAgbGFicyh0aXRsZSA9ICJNb3Rpdm8gZGUgbGEgYXVzZW5jaWEgMjAwNS0yMDE5IiwNCiAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9ICJUcmFiYWpvIC8gRXN0dWRpbyAvIFNlIGNhc8OzIG8gdW5pw7MgLyBEaXZvcmNpw7MgbyBzZXBhcsOzIC8gUmV1bmlyc2UgY29uIHVuIGZhbWlsaWFyIiwNCiAgICAgICAgICAgICAgICB5ID0gIlJhdGUiLA0KICAgICAgICAgICAgICAgIHggPSAiWWVhciIsDQogICAgICAgICAgICAgICAgY29sb3IgPSAiU2VyaWVzIikgKw0KICAgICAgICAgICAgZmFjZXRfd3JhcCguIH4gR3JvdXApIA0KYGBgDQoNCiMjIyBOaXZlbCAzOiBNb3Rpdm9zIGRlIGF1c2VuY2lhIGVuIGdlbmVyYWwgICB2DQoNCkEgY29udGludWFjacOzbiBzZSBtdWV0cmFuIGxvcyBkYXRvcyBkZXNnbG9zYWRvcyBwb3IgbW90aXZvIGRlIGxhIGF1c2VuY2lhLiAgICANCg0KYGBge3IsZWNobyA9IFRSVUV9DQpmY3N0MyA8LSBhZ2d0cyhmLm1vZGVsbzIsIGxldmVscyA9IDMpDQpncm91cHMgPC0gYWdndHMoTW9kZWxvMiwgbGV2ZWxzID0gMykNCnRhYmxhIDwtIHRzKHJiaW5kKGdyb3VwcywgZmNzdDMpLCBzdGFydCA9IHN0YXJ0KGdyb3VwcyksIGZyZXF1ZW5jeSA9IDQpICNGcmVjdWVuY2lhIGFsIGHDsW8NCmBgYA0KDQpgYGB7ciwgZmlnLndpZHRoID0gMTMsZmlnLmhlaWdodCA9IDEzfQ0KYXNfdGliYmxlKHRhYmxhWywtMV0pICU+JQ0KIHRpZHlyOjpnYXRoZXIoU2VyaWVzKSAlPiUNCiAgbXV0YXRlKERhdGUgPSByZXAodGltZSh0YWJsYSksIE5DT0wodGFibGEpIC0gMSksDQogICAgICAgICBHcm91cCA9IHN0cl9leHRyYWN0KFNlcmllcywgIihbQS1aYS16IF0qKSIpLA0KICAgICAgICAgTW90aXZvID0gc3RyaW5ncjo6c3RyX3N1YihTZXJpZXMsIDUsIDcpKSAlPiUNCiAgIGdncGxvdChhZXMoeCA9IERhdGUsIHkgPSB2YWx1ZSwgZ3JvdXAgPSBTZXJpZXMsIGNvbG91ciA9IFNlcmllcykpICsNCiAgICBnZW9tX2xpbmUoKSArDQogICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDIwMTksIGNvbG9yID0gIiNBOEFCRDciLCBsaW5ldHlwZT0gImRhc2hlZCIpICsNCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIA0KICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9OTAsIGhqdXN0PTEpLA0KICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KSwNCiAgICAgICAgICAgICBsZWdlbmQua2V5LndpZHRoPXVuaXQoMC4yLCAiY20iKSwNCiAgICAgICAgICAgICBsZWdlbmQua2V5LmhlaWdodCA9IHVuaXQoMCwgImNtIiksDQogICAgICAgICAgICAgbGVnZW5kLnNwYWNpbmcueCA9IHVuaXQoMC4xLCAiY20iKSwNCiAgICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuMDEsICJsaW5lcyIpLA0KICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArDQogICAgICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZCgpICsNCiAgICAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNSwgMjAyNSxieSA9IDUpKSArDQogICAgICAgICAgZ3VpZGVzKGNvbCA9IGd1aWRlX2xlZ2VuZChuY29sID0gMTUpKSArDQogICAgICAgICAgIGxhYnModGl0bGUgPSAiTW90aXZvIGRlIGxhIGF1c2VuY2lhIDIwMDUtMjAxOSIsDQogICAgICAgICAgICAgICAgc3VidGl0bGUgPSAiVHJhYmFqbyAvIEVzdHVkaW8gLyBTZSBjYXPDsyBvIHVuacOzIC8gRGl2b3JjacOzIG8gc2VwYXLDsyAvIFJldW5pcnNlIGNvbiB1biBmYW1pbGlhciIsDQogICAgICAgICAgICAgICAgeSA9ICJSYXRlIiwNCiAgICAgICAgICAgICAgICB4ID0gIlllYXIiLA0KICAgICAgICAgICAgICAgIGNvbG9yID0gIlNlcmllcyIpICsNCiAgICAgICAgICAgIGZhY2V0X3dyYXAoLn4gR3JvdXAgKyBNb3Rpdm8pDQpgYGANCg0KDQojIFJlZmVyZW5jaWFzDQoNCkF0aGFuYXNvcG91bG9zLCBHLCBIeW5kbWFuLCBSSiwgS291cmVudHplcywgTiwgYW5kIFBldHJvcG91bG9zLCBGICgyMDE3KS4gRm9yZWNhc3Rpbmcgd2l0aCBUZW1wb3JhbCBIaWVyYXJjaGllcy4gRXVyb3BlYW4gSm91cm5hbCBvZiBPcGVyYXRpb25hbCBSZXNlYXJjaCAyNjIoMSksIDYw4oCTNzQuICAgDQoNCkNvY2hyYW4sIFcuRy4gKDE5NzcpLCBTYW1wbGluZyBUZWNobmlxdWVzLiBKb25oIFdpbGV5IGFuZCBTb25zLCBOZXcgWW9yay4gICANCg0KRW5jdWVzdGEgTmFjaW9uYWwgZGUgT2N1cGFjacOzbiB5IEVtcGxlbyAoRU5PRSksIHBvYmxhY2nDs24gZGUgMTUgYcOxb3MgeSBtw6FzIGRlIGVkYWQuICgyMDIwKS4gNTAgcHJlZ3VudGFzIHkgcmVzcHVlc3Rhcy4gSW5zdGl0dXRvIE5hY2lvbmFsIGRlIEVzdGFkw61zdGljYSBHZW9ncmFmw61hIGUgSW5mb3Jtw6F0aWNhLiBSZXRyaWV2ZWQgTWF5IDcsIDIwMjAsIGZyb20gaHR0cHM6Ly93d3cuaW5lZ2kub3JnLm14L3Byb2dyYW1hcy9lbm9lLzE1eW1hcy9kZWZhdWx0Lmh0bWwjRG9jdW1lbnRhY2lvbiAgIA0KDQoNCkZvcmVjYXN0aW5nIEhpZXJhcmNoaWNhbCBUaW1lIFNlcmllcyB1c2luZyBSIC0gQnJpbGxpbyBEYXRhIFNjaWVuY2UgLSBNZWRpdW0uIChuLmQuKS4gUmV0cmlldmVkIE1hcmNoIDMwLCAyMDIwLCBmcm9tIGh0dHBzOi8vbWVkaXVtLmNvbS9icmlsbGlvLWRhdGEtc2NpZW5jZS9mb3JlY2FzdGluZy1oaWVyYXJjaGljYWwtdGltZS1zZXJpZXMtdXNpbmctci01OTg4MjhkYmE0MzUgICANCg0KUi4gSi4gSHluZG1hbiBhbmQgQS4gS29laGxlciAoMjAwNiksIEFub3RoZXIgbG9vayBhdCBtZWFzdXJlcyBvZiBmb3JlY2FzdCBhY2N1cmFjeSwgSW50ZXJuYXRpb25hbCBKb3VybmFsIG9mIEZvcmVjYXN0aW5nLCAyMiwgNjc5LTY4OC4gIA0KDQpIeW5kbWFuIFIuSi4sIEFobWVkIFIuQS4sIEF0aGFuYXNvcG91bG9zIEcuLCBTaGFuZyBILkwuLCAoMjAxMSksIE9wdGltYWwgY29tYmluYXRpb24gZm9yZWNhc3RzIGZvciBoaWVyYXJjaGljYWwgdGltZSBzZXJpZXMsIENvbXB1dGF0aW9uYWwgU3RhdGlzdGljcyAmIERhdGEgQW5hbHlzaXMgNTUoOSksIDI1NzkgLTI1ODkuICANCg0KSHluZG1hbiwgUi4gSi4sIEF0aGFuYXNvcG91bG9zLCBHLiwgJiBTaGFuZywgSC4gTC4gKDIwMTQpLiBodHM6IEFuIFIgUGFja2FnZSBmb3IgRm9yZWNhc3RpbmcgSGllcmFyY2hpY2FsIG9yIEdyb3VwZWQgVGltZSBTZXJpZXMuIGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9odHMvdmlnbmV0dGVzL2h0cy5wZGY/Zm9yY2VkZWZhdWx0PXRydWUgICAgICAgDQoNCkh5bmRtYW4sIFJKICgyMDE3KS4gZm9yZWNhc3Q6IEZvcmVjYXN0aW5nIEZ1bmN0aW9ucyBmb3IgVGltZSBTZXJpZXMgYW5kIExpbmVhciBNb2RlbHMuIFIgcGFja2FnZSB2ZXJzaW9uIDguMS4gaHR0cDovL3BrZy5yb2JqaHluZG1hbi5jb20vZm9yZWNhc3QuICAgDQoNCiANCiMgTGlicmVyw61hcyAgDQoNCioqTGlicmVyw61hcyBxdWUgc2UgdXNhcm9uIGVuIGVsIHRyYWJham8qKiAgIA0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KbmFtZXMoc2Vzc2lvbkluZm8oKSRvdGhlclBrZ3MpDQpgYGANCg0KTm9zIGhhIHNlcnZpZG8gYSBjb25zdHJ1aXIgbW9kZWxvcyBkZSBzZXJpZXMgZGUgdGllbXBvIGNvbiBkYXRvcyBlc3RydWN0dXJhbGVzIHBhcmEgZmluZXMgZGUgcHJvbsOzc3RpY29zLiANCg0KDQoNCjxhIHJlbD0gImxpY2Vuc2UiIGhyZWY9ICJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS80LjAvIj48aW1nIHNyYz0gImh0dHBzOi8vaS5jcmVhdGl2ZWNvbW1vbnMub3JnL2wvYnkvNC4wLzg4eDMxLnBuZyIgYWx0PSAiQ3JlYXRpdmUgQ29tbW9ucyBMaWNlbmNlIiBzdHlsZT0gImJvcmRlci13aWR0aDowIi8+PC9hPjxiciAvPlRoaXMgd29yayBieSBbKipEaWFuYSBWaWxsYXNhbmEgT2NhbXBvKipde3htbG5zOmNjPSAiaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiBwcm9wZXJ0eSA9ICJjYzphdHRyaWJ1dGlvbk5hbWUifSBpcyBsaWNlbnNlZCB1bmRlciBhIDxhIHJlbD0gImxpY2Vuc2UiIGhyZWY9ICJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS80LjAvIj5DcmVhdGl2ZSBDb21tb25zIEF0dHJpYnV0aW9uIDQuMCBJbnRlcm5hdGlvbmFsIExpY2Vuc2U8L2E+Lg0KDQo=